定義
MyBatis屬於數據庫相關的一個Java持久層框架,用於簡化JDBC操作。 它支持定製化 SQL、存儲過程以及高級映射。MyBatis 避免了幾乎所有的 JDBC 代碼和手動設置參數以及獲取結果集。MyBatis 可以使用簡單的 XML 或註解來配置和映射原生信息, 只需要編寫對應的接口類而不需要寫實現類,就能夠完成對數據庫的CRUD操作。
每個MyBatis應用程序主要都是使用SqlSessionFactory實例的,一個SqlSessionFactory實例可以通過SqlSessionFactoryBuilder獲得。SqlSessionFactoryBuilder可以從一個xml配置文件或者一個預定義的配置類的實例獲得。
優點
把sql語句提出到xml文件中,不再有Dao文件。
降低了java代碼和sql語句的耦合度
MyBatis的基本配置
MyBatis的基本配置流程如下:
1.導入JAR包
使用MyBatis需要導入MyBatis和數據庫驅動jar包,如下所示:
<!-- MyBatis jar包 --> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.4.6</version> </dependency> <!-- mysql驅動jar包 --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.48</version> </dependency>
2.編寫接口類
只需要編寫對應的接口類而不需要寫實現類,就能夠完成對數據庫的CRUD操作。
3.編寫接口類對應的Mapper映射器
一個接口類對應一個Mapper的xml文件,格式如下:
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <!-- namespace: 命名空間 (內容爲接口類的全名)每一個Mapper.java會有一個對應的Mapper.xml文件 --> <mapper namespace="xxx.xxxMapper"> //... </mapper>
4.編寫MyBatis的配置文件
<?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> <!-- 用於控制檯輸出日誌內容 --> <!-- <settings> <setting name="logImpl" value="STDOUT_LOGGING"></setting> </settings> --> <!-- environments標籤內部可以配置多個environment,通過default選擇出需要加載的一個數據庫環境 --> <environments default="development"> <!-- id值爲development的開發環境 --> <environment id="development"> <!-- 事務管理,使用JDBC管理 --> <transactionManager type="JDBC"/> <!-- 數據源,使用數據庫連接池 --> <dataSource type="POOLED"> <property name="driver" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/mydb3?useUnicode=true; characterEncoding=utf-8;useSSL=false"/> <property name="username" value="root"/> <property name="password" value="root"/> </dataSource> </environment> <!-- 後面還可以配置多個environment --> <environment id="xxx"> ... </environment> </environments> <!-- 配置Mapper映射器的路徑 --> <mappers> <mapper resource="mapper/xml/TClassMapper.xml"></mapper> <!-- 如果有多個mapper,則在後面繼續添加對應的mapper --> </mappers> </configuration>
配置詳解如下:
mappers(引入映射器)
常用的引入映射器方法有3種,如下所示:
- 1.使用文件路徑引入映射器
<mappers> <mapper resource="mapper/xml/TClassMapper.xml"></mapper> </mappers>
- 2.使用包名引入映射器
<mappers> <package resource="mapper.xml"></package > </mappers>
- 3.使用類註冊引入映射器
<mappers> <class resource="mapper.xml.TClassMapper"></class > </mappers>
MyBatis的組成
MyBatis的組成如下所示:
詳解如下:
1.SqlSessionFactoryBuilder(構造器)
根據配置信息或代碼生成SqlSessionFactory接口。
2.SqlSessionFactory(工廠接口)
MyBatis的應用都是以SqlSessionFactory的實例爲中心,用來生成SqlSession
3.SqlSession(Sql處理器)
SQLSession是一個接口類,類似於JDBC的Connection對象,有如下兩種執行方法返回執行結果:
- 獲取Mapper接口類映射器
讓Mapper映射器通過命名空間和方法名稱去找到對應的SQL,發送到數據庫並執行,返回結果。
- 直接執行SQL語句
SqlSession支持事務,可以通過commit()和rollback()方法來提交或者回滾事務。
4.Sql Mapper(映射規則及SQL定義)
Sql Mapper即Mapper映射器,MyBatis的新設計組件,由Java接口和XML文件(或註解)構成,需要給出對應的SQL和映射規則。負責發送SQL去執行。並返回結果。
Mapper映射器配置
1.元素
<mapper>裏面有如下元素:
select 映射查詢語句
最常用最複雜的元素。可以自定義參數,返回結果集等
update 映射更新語句
執行後返回一個整數,代表更新的條數。
delete 映射刪除語句
執行後返回一個整數,代表刪除的條數。
insert 映射插入語句
執行後返回一個整數,代表插入的條數。
sql 允許定義一部分的sql,然後可以在各個地方引用它 resultMap 用來描述從數據庫中查詢出來的結果集中來加載對象 cache 給命名空間緩存配置 cache-ref 其他命名空間緩存配置引用 2.元素的屬性
id 唯一標識符,需要和Mapper接口類中對應的方法名一樣 parameterType 傳入參數類型 resultType 返回結果類型
如果返回結果是一個數字,則可以不用寫
如果返回結果是一個實體類,則resultType="實體類名"
如果返回結果是一個List<T>集合,則resultType="T"
如果返回結果是一個Map集合,則resultType="map"
resultMap 外部resultMap的命名引用 timeout 這個設置是在拋出異常之前,驅動程序等待數據庫返回請求結果的秒數。 fetchSize 影響驅動程序每次批量返回的結果行數。
Mapper的實現原理
MapperProxyFactory中,使用JDK的動態代理生成Mapper接口的代理代理類由動態處理器MapperProxy中調用MapperMethod中的方法處理執行SQL,最後,在MapperMethod中根據執行的方法返回值決定調用SqlSession中的對應方法執行SQL
動態SQL語句
Sql標籤
有如下標籤:
if 表示判斷是否需要添加某個條件,用於SQL語句的拼接
使用if標籤的時候,需要使用“where 1=1”, 做sql語句的拼接。避免出現sql語法錯誤(因爲缺少where關鍵字)
where 用於拼接select和delete語句
set 用於拼接update語句
trim 用於替代set和where標籤,可以拼接select、delete、update語句
- if標籤
<select id="getEmps" parameterType="entity.Emp" resultType="entity.Emp"> select * from emp where 1=1 <if test="empName!=null">and empName=#{empName}</if> <if test="empAge!=0">and empAge > #{empAge}</if> </select>
- where標籤
<select id="getEmpsByWhere" parameterType="entity.Emp" resultType="entity.Emp"> select * from emp <!-- 如果if條件中,有爲true的條件,那麼會添加一個where關鍵字,同時會去掉where後面的第一個and關鍵字 --> <where> <if test="empName!=null">and empName=#{empName}</if> <if test="empAge!=0">and empAge > #{empAge}</if> </where> </select>
- set標籤
<update id="updateEmpSet" parameterType="entity.Emp"> update emp <!-- set標籤 set中的if標籤,條件爲真的情況,就會拼在sql語句中, 將最後的“,”去掉。 set中的if標籤, 條件都爲假的情況,就會出現sql語法錯誤。 --> <set> <if test="empName!=null">empName=#{empName},</if> <if test="empAge!=0">empAge=#{empAge},</if> <if test="empJob!=null">empJob=#{empJob},</if> <if test="deptNo!=0">deptNo=#{deptNo}</if> </set> <where> <if test="empNo!=0">and empNo=#{empNo}</if> </where> </update>
- trim標籤
<!-- trim的使用:替代set和where標籤, 通過屬性的設置,保證sql語句的語法正確 ) prefix : 添加前綴 prefixOverrides: 刪除前面的某個內容 suffix: 添加後綴 suffixOverrides: 刪除後面的某個內容 --> <!-- 替代where --> <select id="getEmpsTrim" parameterType="entity.Emp" resultType="entity.Emp"> select * from emp <trim prefix="where" prefixOverrides="and"> <if test="empName!=null">and empName=#{empName}</if> <if test="empAge!=0">and empAge>#{empAge}</if> <if test="empJob!=null">and empJob like #{empJob}</if> </trim> </select> <!-- 替代set --> <select id="updateEmpSet" parameterType="entity.Emp"> update emp <trim prefix="set" suffixOverrides="," suffix=" where empNo=#{empNo}"> <if test="empName!=null">empName=#{empName},</if> <if test="empAge!=0">empAge=#{empAge},</if> <if test="empJob!=null">empJob=#{empJob},</if> <if test="deptNo!=0">deptNo=#{deptNp}</if> </trim> </select>
分頁查詢
select * from tableName limit begin, maxRow; begin:查詢數據的起點 maxRow:表示查詢多少的數據(每頁的數量) 分頁: 每頁顯示的行數:maxRow 當前是第幾頁:page 計算出begin: begin (page-1)*maxRow 計算總頁數:pages rows/maxRow + 1 計算總行數:rows select count(*) from tableName
導入分頁查詢插件jar包
<dependency> <groupId>com.github.pagehelper</groupId> <artifactId>pagehelper</artifactId> <version>5.1.10</version> </dependency>
在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> <!-- 分頁插件的配置 --> <plugins> <plugin interceptor="com.github.pagehelper.PageInterceptor"> <!-- value:表示傳入參數(page,rows)不合理時的處理方式 爲true時:若page表示的頁面不存在時,如page<1,那麼page設爲1;如果page>最後一頁,那麼page設置爲最後一頁 爲false時:若page表示的頁面不存在時,查詢內容爲空 --> <property name="reasonable" value="true"></property> </plugin> </plugins> .... </configuration>
使用相關類進行分頁
public class TestStudent { @Test public void getStudents() throws IOException { SqlSession sqlSession = getSqlSession(); StudentMapper studentMapper = sqlSession.getMapper(StudentMapper.class); //調用PageHelper的靜態方法設置要分頁的頁碼和每頁顯示的數量(需要先設置分頁的參數,然後才能再查詢數據庫) PageHelper.startPage(5, 5); List<Student> students = studentMapper.getStudents(); //PageInfo:存放分頁相關數據,創建對象的時候,需要一個查詢的結果List作爲參數, // 需要設置泛型,泛型就是當前查詢的實體類 PageInfo<Student> pageInfo = new PageInfo<>(students); System.out.println("總記錄數: " + pageInfo.getTotal()); System.out.println("總頁數: " + pageInfo.getPages()); System.out.println("每頁的數量: " + pageInfo.getPageSize()); System.out.println("當前頁: " + pageInfo.getPageNum()); for (Student student : students) { System.out.println(student); } } public SqlSession getSqlSession() throws IOException { String resource = "mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream); return sessionFactory.openSession(); } }
使用MyBatis Generator插件
1.說明
使用MyBatis Generator插件可以自動生成數據庫對應的表的實體類,mapper映射器類和mapper.xml文件。
2.導入MyBatis Generator插件
點擊STS的Help選項,然後點擊其中的Eclipse Marketplace。然後在搜索框裏面搜索mybatis generator,然後點擊下載安裝MyBatis Generator插件。如下圖所示:
3.使用
在資源文件夾裏面右鍵,點擊new選擇生成MyBatis Generator Configuration File。如下圖所示:
生成的文件如下所示:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE generatorConfiguration PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN" "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd"> <generatorConfiguration> <context id="context1"> <jdbcConnection connectionURL="???" driverClass="???" password="???" userId="???" /> <javaModelGenerator targetPackage="???" targetProject="???" /> <sqlMapGenerator targetPackage="???" targetProject="???" /> <javaClientGenerator targetPackage="???" targetProject="???" type="XMLMAPPER" /> <table schema="???" tableName="???"> <columnOverride column="???" property="???" /> </table> </context> </generatorConfiguration>
然後根據所選的數據庫表進行配置,配置好的如下所示:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE generatorConfiguration PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN" "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd"> <generatorConfiguration> <context id="context1"> <!-- 數據庫連接 --> <jdbcConnection connectionURL="jdbc:mysql://localhost:3306/crm?useUnicode=true& characterEncoding=utf-8&useSSL=false" driverClass="com.mysql.jdbc.Driver" password="root" userId="root" /> <!-- Java實體類所在包名稱和項目名稱 --> <javaModelGenerator targetPackage="com.luckylas.crm.entity" targetProject="crm/src/main/java" /> <!-- mapper.xml所在的包(targetPackage)和所在的項目(targetProject) --> <sqlMapGenerator targetPackage="com.luckylas.crm.mapper.xml" targetProject="crm/src/main/java" /> <!-- mapper所在的包(targetPackage)和所在的項目(targetProject) --> <javaClientGenerator targetPackage="com.luckylas.crm.mapper" targetProject="crm/src/main/java" type="XMLMAPPER" /> <!-- tableName標籤表示數據庫中的表,可以有多個, schema:用於指定實體類的名字,不指定則默認是表名的首字母大寫 --> <table schema="User" tableName="user"> <!-- columnOverride表示將數據庫表中字段名,在實體類中取一個新的名字。如果不指定,則會默認值--> <!-- <columnOverride column="UId" property="u_id" /> --> </table> </context> </generatorConfiguration>
一個簡單的MyBatis實例
創建數據庫實體類,和數據庫字段一一對應
/** * 班級實體類 * @author luckyliuqs */ public class TClass { private int cid; //班級ID private String cname; //班級名稱 public TClass() {} public TClass(int cid, String cname) { super(); this.cid = cid; this.cname = cname; } public int getCid() { return cid;} public void setCid(int cid) {this.cid = cid;} public String getCname() {return cname;} public void setCname(String cname) {this.cname = cname;} @Override public String toString() { return "TClass [cid=" + cid + ", cname=" + cname + "]"; } }
編寫數據庫接口Mapper類
public interface TClassMapper { public List<TClass> getAll(); //獲取所有班級信息 public int insert(TClass tClass); //插入指定班級信息 public void delete(int cid); //刪除指定班級信息 public void update(TClass tClass); //更新指定班級信息 }
編寫接口類對應的Mapper文件
如下所示:TClassMapper.xml
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <!-- namespace: 命名空間 (內容爲接口Mapper類的全名),每一個Mapper.java會有一個對應的Mapper.xml件 --> <mapper namespace="mapper.TClassMapper"> <!-- id對應爲接口Mapper類中的方法名 --> <!-- resultType表示返回結果的類型,這裏寫入TClass即可,如果返回結果是一個TClass則會返回這個TClass; 如果返回的是多個TClass的集合,則會自動封裝爲List<TClass>返回 --> <select id="getAll" resultType="entity.TClass"> select * from t_class; </select> <!-- #{s_name}, 這是從方法的參數對象中,取到參數對象中的屬性名,得到其屬性值 --> <insert id="insert" parameterType="tclassMap"> insert into t_class (c_name) values (#{c_name}); </insert> <delete id="delete"> delete from t_class where c_id=#{c_id}; </delete > <update id="update" parameterType="tclassMap"> update t_class set c_name=#{cname} where c_id=#{c_id}; </update > </mapper>
編寫JUnit測試類
/** * 測試類 */ public class TestTClass { @Test public void test() { try { // mybatis的配置文件路徑 String resource = "mybatis-config.xml"; // 獲取到InputStream流,初始化MyBatis配置環境 InputStream input = Resources.getResourceAsStream(resource); // 得到SqlSessionFactory SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(input); // 得到session,打開和數據庫之間的會話 SqlSession session = sessionFactory.openSession(); // 得到接口 TClassMapper clsMapper = session.getMapper(TClassMapper.class); //獲取到所有班級信息 List<TClass> list = clsMapper.getAll(); for(TClass cl : list) { System.out.println(cl); } //插入指定班級信息 TClass tClass = new TClass(0,"美工"); clsMapper.insert(tClass); //刪除指定班級信息 clsMapper.delete(8); //更新指定班級信息 clsMapper.update(tClass); //提交 session.commit(); session.close(); } catch (IOException e) { e.printStackTrace(); } } }
上述使用MyBatis流程如下:
1.獲取MyBatis配置文件 2.獲取配置文件的輸入流InputStream 3.通過輸出流構建工廠SqlSessionFactory 4.通過SqlSessionFactory的openSession()方法獲得SqlSession對象 5.通過SqlSession獲取到對應實體類的Mapper接口類實例 6.通過此接口類執行對應方法
MyBatis與Hibernate的區別
兩者都是持久層框架,區別如下:
Hibernate 是一個標準的ORM框架,比較重量級,學習成本高。
優點:高度封裝,使用起來不用寫SQL語句,開發週期短
缺點:SQL語句無法優化
應用場景:在於用量不大,併發量小的場景
MyBatis 不是一個ORM框架,只是對JDBC的輕量級封裝。
優點:學習成本低,SQL語句可以優化,執行效率高,速度快
缺點:編碼量大,開發週期長
應用場景:用戶量大,高併發
參考:https://www.jianshu.com/p/24302ca0e099