mybatis01-簡介
文章目錄
0.拓展
1.jdbc操作數據庫
1.1 maven依賴
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>mybatis-study</artifactId>
<groupId>com.myx</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<packaging>jar</packaging>
<artifactId>jdbc-demo</artifactId>
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.2</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>4.1.19</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.6.1</version>
</dependency><dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.30</version>
</dependency>
</dependencies>
</project>
1.2 java代碼
import java.sql.*;
/**
* 描述:jdbc test
* @author: myx
* @date: 2019/1/7
* 注意:本內容僅限于學習使用
* Copyright 2019-myx. All rights reserved.
*/
public class JdbcTest {
public static void main(String[] args) {
Connection connection = null;
PreparedStatement preparedStatement = null;
ResultSet resultSet = null;
try {
//加載數據庫驅動
Class.forName("com.mysql.jdbc.Driver");
//通過驅動管理類獲取數據庫鏈接
connection = DriverManager.getConnection("jdbc:mysql://140.143.193.83:3306/mybatis-test?characterEncoding=utf-8","iot", "123456");
//定義sql語句 ?表示占位符
String sql = "select * from user where username = ?";
//獲取預處理statement
preparedStatement = connection.prepareStatement(sql);
//設置參數,第一個參數為sql語句中參數的序號(從1開始),第二個參數為設置的參數值
preparedStatement.setString(1, "myx");
//向數據庫發出sql執行查詢,查詢出結果集
resultSet = preparedStatement.executeQuery();
//遍歷查詢結果集
while(resultSet.next()){
System.out.println(resultSet.getString("id")+" "+resultSet.getString("username"));
}
} catch (Exception e) {
e.printStackTrace();
}finally{
//釋放資源
if(resultSet!=null){
try {
resultSet.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(preparedStatement!=null){
try {
preparedStatement.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(connection!=null){
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
}
1.3 傳統 JDBC 的弊端
- jdbc 底層沒有用連接池、操作數據庫需要頻繁的創建和關聯鏈接。消耗很大的資源
- 寫原生的 jdbc 代碼在java中,一旦我們要修改sql的話,java需要整體編譯,不利于系 統維護
- 使用 PreparedStatement預編譯的話對變量進行設置123數字,這樣的序號不利于維護
- 返回 result 結果集也需要硬編碼。
2.現階段數據訪問層框架
2.什么是mybatis
MyBatis 是一款優秀的持久層框架,它支持定制化 SQL、存儲過程以及高級映射。MyBatis 避免了幾乎所有的 JDBC 代碼和手動設置參數以及獲取結果集。MyBatis 可以使用簡單的 XML 或注解來配置和映射原生信息,將接口和 Java 的 POJOs(Plain Old Java Objects,普通的 Java對象)映射成數據庫中的記錄。
2.1 參考手冊
2.2 mybatis架構
try {
// 1.mybatis配置文件
String resources = "mybatis.xml";
// 2.獲取Reader對象
Reader resourceAsReader = Resources.getResourceAsReader(resources);
// 3.獲取SqlSessionFactoryBuilder
SqlSessionFactory build = new SqlSessionFactoryBuilder().build(resourceAsReader);
// 4.創建對應的session
SqlSession sqlSession = build.openSession();
// 5.獲取對應的mapper
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
// 6.執行方法
UserEntity user = userMapper.getUser(1);
System.out.println("name:" + user.getName());
} catch (Exception e) {
e.printStackTrace();
}
3.helloword(xml)
4.mybatis全局注解詳解
5.mybatis注解實現
5.1 mybatis-config.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://140.143.193.83:3306/mybatis-test"/>
<property name="username" value="iot"/>
<property name="password" value="123456"/>
</dataSource>
</environment>
</environments>
<mappers>
<!--xml方式-->
<!--<mapper resource="mapper/UserMapper.xml"/>-->
<!--注解方式-->
<package name="com.myx.mybatis"></package>
</mappers>
</configuration>
5.2 UserMapper
import org.apache.ibatis.annotations.Select;
/**
* 描述:userMapper接口
* @author: myx
* @date: 2019/1/7
* 注意:本內容僅限于學習使用
* Copyright 2019-myx. All rights reserved.
*/
public interface UserMapper {
@Select("select * from user where id =#{id}")
public User selectUser(int id);
}
6.Mybatis 之注解和 xml 優缺點
- Xml:增加 xml 文件、麻煩、條件不確定、容易出錯,特殊字符轉義
- 注釋:不適合復雜 sql,收集 sql 不方便,重新編譯
7.Mybatis 之#與$區別
7.1 #{}表示一個占位符號
通過#{}可以實現preparedStatement向占位符中設置值,自動進行java類型和jdbc類型轉換,#{}可以有效防止sql注入。#{}可以接收簡單類型值或pojo屬性值。 如果parameterType傳輸單個簡單類型值,#{}括號中可以是value或其它名稱。
7.2 ${}表示拼接sql串
通過${}可以將parameterType傳入的內容拼接在sql中且不進行jdbc類型轉換, {}括號中只能是value。
7.3 OGNL
Object Graphic Navigation Language
對象 圖 導航 語言
它是通過對象的取值方法來獲取數據。在寫法上把get給省略了。
比如:我們獲取用戶的名稱:
- 類中的寫法:user.getUsername();
- OGNL表達式寫法:user.username
mybatis中為什么能直接寫username,而不用user.呢:因為在parameterType中已經提供了屬性所屬的類,所以此時不需要寫對象名。
Mybatis使用ognl表達式解析對象字段的值,#{}或者${}括號中的值為pojo屬性名稱。
8.Mybatis 之 parameterType 與 parameterMap 區別
- parameterMap和resultMap類似,parameterMap通常應用于mapper中有多個參數要傳進來時,表示將查詢結果集中列值的類型一一映射到java對象屬性的類型上,在開發過程中不推薦這種方式。
- parameterType直接將查詢結果列值類型自動對應到java對象屬性類型上,不再配置映射關系一一對應。
9.Mybatis 之 resultType 與 resultMap 區別
- 使用 resultType進行輸出映射,只有查詢出來的列名和pojo中的屬性名一致,該列才可以映射成功。
- mybatis 中使用 resultMap 完成高級輸出結果映射(自定義映射)。
10.mybatis插件
10.1 官網簡介
10.2 實現顯示sql插件
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.ParameterMapping;
import org.apache.ibatis.mapping.ParameterMode;
import org.apache.ibatis.plugin.*;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;
import org.apache.ibatis.type.TypeHandlerRegistry;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Properties;
import java.util.regex.Matcher;
@Intercepts
({
@Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class}),
@Signature(type = Executor.class, method = "update", args = {MappedStatement.class, Object.class})
})
public class SqlPrintInterceptor implements Interceptor{
private static final Logger log = LoggerFactory.getLogger(SqlPrintInterceptor.class);
private static final DateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
@Override
public Object intercept(Invocation invocation) throws Throwable {
MappedStatement mappedStatement = (MappedStatement) invocation.getArgs()[0];
Object parameterObject = null;
if (invocation.getArgs().length > 1) {
parameterObject = invocation.getArgs()[1];
}
long start = System.currentTimeMillis();
Object result = invocation.proceed();
String statementId = mappedStatement.getId();
BoundSql boundSql = mappedStatement.getBoundSql(parameterObject);
Configuration configuration = mappedStatement.getConfiguration();
String sql = getSql(boundSql, parameterObject, configuration);
long end = System.currentTimeMillis();
long timing = end - start;
if(log.isInfoEnabled()){
log.info("執行sql耗時:" + timing + " ms" + " - id:" + statementId + " - Sql:" );
log.info(" "+sql);
}
return result;
}
@Override
public Object plugin(Object target) {
if (target instanceof Executor) {
return Plugin.wrap(target, this);
}
return target;
}
@Override
public void setProperties(Properties properties) {
}
private String getSql(BoundSql boundSql, Object parameterObject, Configuration configuration) {
String sql = boundSql.getSql().replaceAll("[\\s]+", " ");
List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
TypeHandlerRegistry typeHandlerRegistry = configuration.getTypeHandlerRegistry();
if (parameterMappings != null) {
for (int i = 0; i < parameterMappings.size(); i++) {
ParameterMapping parameterMapping = parameterMappings.get(i);
if (parameterMapping.getMode() != ParameterMode.OUT) {
Object value;
String propertyName = parameterMapping.getProperty();
if (boundSql.hasAdditionalParameter(propertyName)) {
value = boundSql.getAdditionalParameter(propertyName);
} else if (parameterObject == null) {
value = null;
} else if (typeHandlerRegistry.hasTypeHandler(parameterObject.getClass())) {
value = parameterObject;
} else {
MetaObject metaObject = configuration.newMetaObject(parameterObject);
value = metaObject.getValue(propertyName);
}
sql = replacePlaceholder(sql, value);
}
}
}
return sql;
}
private String replacePlaceholder(String sql, Object propertyValue) {
String result;
if (propertyValue != null) {
if (propertyValue instanceof String) {
result = "'" + propertyValue + "'";
} else if (propertyValue instanceof Date) {
result = "'" + DATE_FORMAT.format(propertyValue) + "'";
} else {
result = propertyValue.toString();
}
} else {
result = "null";
}
return sql.replaceFirst("\\?", Matcher.quoteReplacement(result));
}
}
11.MyBatis的動態SQL
MyBatis的強大特性之一便是它的動態SQL,以前拼接的時候需要注意的空格、列表最后的逗號等,現在都可以不用手動處理了,MyBatis采用功能強大的基于OGNL的表達式來實現,下面主要介紹下。
11.1 if標簽
if是最常用的判斷語句,主要用于實現某些簡單的條件選擇。基本使用示例如下:
<select id="queryAllUsersByName" resultType="com.example.springboot.mybatisxml.entity.User">
select * from user where 1=1
<if test="name != null and name != ''">
and name = #{name}
</if>
<if test="age != null ">
and age = #{age}
</if>
</select>
11.2 where標簽
上面的例子中使用了“1=1”,是為了避免后續條件不滿足時候報錯,那有沒有辦法避免這種寫法呢?
當然有,就是接下來要說的,標簽會自動判斷如果包含的標簽中有返回值的話,就在sql中插入一個‘where’,如果where標簽最后返回的內容是以and 或者or開頭的,也會被自動移除掉,上面例子中換成“where”標簽后寫法如下:
<select id="queryAllUsersByName" resultType="com.example.springboot.mybatisxml.entity.User">
select * from user
<where>
<if test="name != null and name != ''">
and name = #{name}
</if>
<if test="age != null ">
and age = #{age}
</if>
</where>
</select>
11.3 trim標簽
trim的作用是去除特殊的字符串,它的prefix屬性代表語句的前綴,prefixOverrides屬性代表需要去除的哪些特殊字符串,prefixOverrides屬性會忽略通過管道分隔的文本序列(注意此例中的空格也是必要的),后綴的處理和前綴一樣。
trim標簽的主要屬性如下
- prefix:前綴覆蓋并增加其內容。
- suffix:后綴覆蓋并增加其內容。
- prefixOverrides:前綴判斷的條件。
- suffixOverrides:后綴判斷的條件。
舉兩個例子。
- 使用前綴屬性
<select id="queryAllUsersByName" resultType="com.example.springboot.mybatisxml.entity.User">
select * from user
<trim prefix="WHERE" prefixOverrides="AND |OR " >
<if test="name != null and name != ''">
and name = #{name}
</if>
<if test="sex != null ">
or sex = #{sex}
</if>
<if test="age != null ">
and age = #{age}
</if>
</trim>
</select>
- 使用后綴屬性
<update id="update" parameterType="Object">
UPDATE user
<trim suffix=" SET " suffixOverrides=",">
<if test="id != null ">id=#{id},</if>
<if test="name != null ">name=#{name},</if>
<if test="age != null ">age=#{age},</if>
</trim>
WHERE ID=#{id}
</update>
11.4 foreach標簽
作用是遍歷集合,它能夠很好地支持數組和List、Set接口的集合的遍歷,往往和sql中的in組合比較多。
foreach標簽的主要屬性如下
- item:表示循環中當前的元素。
- index:表示當前元素在集合的位置下標。
- collection:配置list的屬性名等。
- open和close:配置的是以什么符號將這些集合元素包裝起來。
- separator:配置的是各個元素的間隔符。
<select id="queryAllUsersByName" resultType="com.example.springboot.mybatisxml.entity.User">
select * from user where id in
<foreach item="id" index="index" collection="userList"
open="(" separator="," close=")">
#{id}
</foreach>
</select>
智能推薦
【Mybatis01】實現縮小版銀行轉賬+分頁查詢功能
一、實現轉賬 1.1 項目實現圖和結構圖 1.1.1 pojo實體類 !分頁查詢表 1.2 全局文件mybatis.xml的編寫 1.3 mapper.xml的編寫(用來進行查詢!!!) 1.3.1分析: (確保轉賬用戶的正確性)因為需要確認轉賬用戶的賬號密碼輸入正確,所以需要根據賬號和密碼進行表查詢并且拿出查出來的對象,以作后續的余額更改操作! (確保入帳用戶的正確性)同上述,查表,取出對象! ...
mybatis01-簡介
文章目錄 0.拓展 1.jdbc操作數據庫 1.1 maven依賴 1.2 java代碼 1.3 傳統 JDBC 的弊端 2.現階段數據訪問層框架 2.什么是mybatis 2.1 參考手冊 2.2 mybatis架構 3.helloword(xml) 4.mybatis全局注解詳解 5.mybatis注解實現 5.1 mybatis-config.xml 5.2 UserMapper 6.Myb...
freemarker + ItextRender 根據模板生成PDF文件
1. 制作模板 2. 獲取模板,并將所獲取的數據加載生成html文件 2. 生成PDF文件 其中由兩個地方需要注意,都是關于獲取文件路徑的問題,由于項目部署的時候是打包成jar包形式,所以在開發過程中時直接安照傳統的獲取方法沒有一點文件,但是當打包后部署,總是出錯。于是參考網上文章,先將文件讀出來到項目的臨時目錄下,然后再按正常方式加載該臨時文件; 還有一個問題至今沒有解決,就是關于生成PDF文件...
電腦空間不夠了?教你一個小秒招快速清理 Docker 占用的磁盤空間!
Docker 很占用空間,每當我們運行容器、拉取鏡像、部署應用、構建自己的鏡像時,我們的磁盤空間會被大量占用。 如果你也被這個問題所困擾,咱們就一起看一下 Docker 是如何使用磁盤空間的,以及如何回收。 docker 占用的空間可以通過下面的命令查看: TYPE 列出了docker 使用磁盤的 4 種類型: Images:所有鏡像占用的空間,包括拉取下來的鏡像,和本地構建的。 Con...
猜你喜歡
requests實現全自動PPT模板
http://www.1ppt.com/moban/ 可以免費的下載PPT模板,當然如果要人工一個個下,還是挺麻煩的,我們可以利用requests輕松下載 訪問這個主頁,我們可以看到下面的樣式 點每一個PPT模板的圖片,我們可以進入到詳細的信息頁面,翻到下面,我們可以看到對應的下載地址 點擊這個下載的按鈕,我們便可以下載對應的PPT壓縮包 那我們就開始做吧 首先,查看網頁的源代碼,我們可以看到每一...
Linux C系統編程-線程互斥鎖(四)
互斥鎖 互斥鎖也是屬于線程之間處理同步互斥方式,有上鎖/解鎖兩種狀態。 互斥鎖函數接口 1)初始化互斥鎖 pthread_mutex_init() man 3 pthread_mutex_init (找不到的情況下首先 sudo apt-get install glibc-doc sudo apt-get install manpages-posix-dev) 動態初始化 int pthread_...
統計學習方法 - 樸素貝葉斯
引入問題:一機器在良好狀態生產合格產品幾率是 90%,在故障狀態生產合格產品幾率是 30%,機器良好的概率是 75%。若一日第一件產品是合格品,那么此日機器良好的概率是多少。 貝葉斯模型 生成模型與判別模型 判別模型,即要判斷這個東西到底是哪一類,也就是要求y,那就用給定的x去預測。 生成模型,是要生成一個模型,那就是誰根據什么生成了模型,誰就是類別y,根據的內容就是x 以上述例子,判斷一個生產出...
styled-components —— React 中的 CSS 最佳實踐
https://zhuanlan.zhihu.com/p/29344146 Styled-components 是目前 React 樣式方案中最受關注的一種,它既具備了 css-in-js 的模塊化與參數化優點,又完全使用CSS的書寫習慣,不會引起額外的學習成本。本文是 styled-components 作者之一 Max Stoiber 所寫,首先總結了前端組件化樣式中的最佳實踐原則,然后在此基...