. Mybatis
1 什麼是 Mybatis
Mybatis 是對 JDBC 的封裝,它隱藏了具體的 JDBC 的 API ,它把 SQL 語句放到了配置文件中,它能自動把不同的輸入數據映射到 SQL 語句的動態參數上,它能自動把 SQL 語句的執行結果映射爲 JAVA 對象…… MyBatis 是一個持久化層的框架!
Mybatis 是一個 ORM 框架
可以說 Mybatis 是一個半自動的 ORM 框架 ,Hibernate 是全自動的
2 主配置文件
基本作用就是配置 JDBC 連接的有關信息,比如 URL 、用戶名、密碼等等
如:
<? 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 > <!-- 別名 --> < typeAliases > < typeAlias type = "org.leadfar.mybatis.Person" alias = "Person" /> </ typeAliases > <!-- 配置數據庫連接信息 --> < 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://localhost/mybatis" /> < property name = "username" value = "root" /> < property name = "password" value = "leadfar" /> </ dataSource > </ environment > </ environments > <!-- 映射文件定位 --> < mappers > < mapper resource = "org/leadfar/mybatis/PersonMapper.xml" /> </ mappers > </ configuration >
|
3 映射文件
基本作用就是編寫 SQL 語句,同時給每個 SQL 語句定義一個唯一標識( ID ),在程序中通過此 ID 來調用這條SQL 語句。
<? 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" > <!-- 整個唯一標識 sql 的 id 爲 namespace+id org.leadfar.mybatis.Person.insert--> < mapper namespace = "org.leadfar.mybatis.Person" > < insert id = "insert" parameterType = "Person" > insert into t_person(name,age,birthday) values(#{name},#{age},#{birthday}) </ insert >
</ mapper > |
4 程序代碼
// 聲明一個 session 管理工廠 SqlSessionFactory factory = null ; // 聲明讀取器 Reader reader = null ; try { // 通過讀取器定位到主配置文件 reader = Resources.getResourceAsReader ( "SqlMapConfig.xml"); // 初始化工廠 factory = new SqlSessionFactoryBuilder().build(reader); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } // 打開一個會話 ( 類似於 jdbc 中創建數據庫連接 ) SqlSession session = factory.openSession(); Person p = new Person(); p.setName( " 張三 " ); p.setAge(11); p.setBirthday( new Date()); // 進行插入 try { session.insert( "org.leadfar.mybatis.Person.insert" , p); // 事務提交 session.commit(); System. out .println( " 保存成功 !" ); } catch (Exception e) { e.printStackTrace(); // 事務回滾 session.rollback(); } finally { // 關閉連接 session.close(); } |
5sql 參數傳遞
1. 簡單參數
< delete id = "delete" parameterType = "int" > delete from t_person where id=#{id} <!— 無所謂寫什麼都可以 à </ delete > |
2. 多個參數,建議採用 Map 包裝
< select id = "selectLikeNameAndAgeBetween" parameterType = "map"resultType = "Person" > < include refid = "selectBasic" /> where name like #{name} and age between #{age1} and #{age2} </ select >
|
SqlSession session = factory .openSession(); Map map = new HashMap(); map .put( "name" , "% 張 %" ); map .put( "age1" , 0); map .put( "age2" , 100); List persons=session.selectList(Person. class .getName()+".selectLikeNameAndAgeBetween" ,map );
System. out .println(((Person)(persons.get(0))).getName()); session.close(); |
6sql 語句塊
< sql id = "selectBasic" > select * from t_person </ sql > < select id = "selectLikeName" parameterType = "string" resultType ="Person" > < include refid = "selectBasic" /> where name like #{name} </ select > |
7 屬性名與字段名不匹配
< resultMap type = "Person" id = "select-reusltMap" >
< result column = "sex" property = "gender" />
</ resultMap >
< select id = "selectLikeNameAndAgeBetweenResultMap" parameterType = "map" resultMap ="select-reusltMap" >
< include refid = "selectBasic" /> where name like #{name} and age between #{age1} and #{age2}
</ select >
8 動態 sql
8.1 .if
< select id = "selectIf" parameterType = "map" resultType = "Person" > select * from t_person < if test = "name !=null" > where name like #{name} </ if > < if test = "age !=0" > and age=#{age} </ if > </ select > |
注:如果 name==null ,則 sql 拼寫錯誤
< select id = "selectWhere" parameterType = "map" resultType = "Person" > select * from t_person < where > < if test = "name !=null" > name like #{name} </ if > < if test = "age !=0" > and age=#{age} </ if > </ where > </ select > |
注 : 加 <where> 後則確保一定是 where 開頭
8.2 .choose
類似於 switch
< select id = "selectChoose" parameterType = "map" resultType = "Person" > select * from t_person < choose > < when test = "name!=null" > where name like #{name} </ when > < otherwise > where name like '%%' </ otherwise > </ choose > < if test = "age !=0" > and age=#{age} </ if > </ select > |
8.3 .foreach
如 in 操作
< select id = "selectFor" parameterType = "list" resultType = "Person" > select * from t_person where id in < foreach collection = "list" item = "p" open = "(" close = ")" separator= "," > #{p} </ foreach > </ select > |
SqlSession session = factory .openSession(); List l = new ArrayList(); l .add(1); l .add(2); l .add(3); l .add(4); List persons=session.selectList(Person. class .getName()+".selectFor" ,l );
System. out .println(((Person)(persons.get(1))).getName()); session.close(); |
8.4 $
相當於轉義,字符串替換
< select id = "selectIn" parameterType = "map" resultType = "Person" > select * from t_person where id in ${instr} </ select > |
SqlSession session = factory .openSession();
Map params= new HashMap(); //params.put("name", "% 張 %"); params.put( "instr" , "(1,2,3,4)" ); List persons=session.selectList(Person. class .getName()+".selectIn" ,params);
System. out .println(((Person)(persons.get(1))).getName()); session.close(); |
另外對於排序時由外部傳入某字段
< select id = "selectOrderBy" parameterType = "map" resultType = "Person" > select * from t_person order by ${by}
</ select > |
SqlSession session = factory .openSession();
Map params= new HashMap(); //params.put("name", "% 張 %"); params.put( "by" , "age desc" ); List persons=session.selectList(Person. class .getName()+".selectOrderBy" ,params);
System. out .println(((Person)(persons.get(1))).getName()); session.close(); |
9 一對一映射
9.1 簡單方法
設 Person 與 Address 是一對一關係
PersonMapper.xml
< resultMap type = "Person" id = "select-resultMap" > <!-- 一對一 ( 多對一 ) 通過 association,property 目標對象的屬性 --> < association property = "address" select ="org.leadfar.mybatis.Address.selectAll" column = "id" javaType = "Address">
</ association >
</ resultMap > |
< select id = "selectAll" resultMap = "select-resultMap" > select * from t_person </ select > |
AddressMapper.xml
< select id = "selectAll" parameterType = "int" resultType = "Address" > select * from t_address where person_id=#{pId} </ select > |
9.2 解決 N+1 問題
< select id = "selectAllN1" resultMap = "select-resultMapN1" > select a.*,b.id addr_id, b.postCode,b.area from t_person a left join t_address b on a.id=b.person_id </ select > |
<!-- 這種方式能解決 N+1 問題,但是自動對象賦值將不行 --> < resultMap type = "Person" id = "select-resultMapN1" > < id column = "id" property = "id" /> < result column = "sex" property = "gender" /> < result column = "name" property = "name" /> < result column = "birthday" property = "birthday" /> < result column = "age" property = "age" /> < association property = "address" column = "id" javaType ="Address" > < id column = "addr_id" property = "id" /> < result column = "area" property = "area" /> < result column = "postCode" property = "postCode" /> </ association > </ resultMap > |
6.10 一對多映射
設 Person 和 Car 爲一對多關係
< select id = "selectAllN1" resultMap = "select-resultMapN1" > select a.*,b.id addr_id, b.postCode,b.area from t_person a left join t_address b on a.id=b.person_id </ select > |
<!-- 這種方式能解決 N+1 問題,但是自動對象賦值將不行 -->
< resultMap type = "Person" id = "select-resultMapN1" >
< id column = "id" property = "id" />
< result column = "sex" property = "gender" />
< result column = "name" property = "name" />
< result column = "birthday" property = "birthday" />
< result column = "age" property = "age" />
< association property = "address" column = "id" javaType ="Address" >
< id column = "addr_id" property = "id" />
< result column = "area" property = "area" />
< result column = "postCode" property = "postCode" />
</ association >
<!-- 將 t_car 中相關的數據與目標對象 (Person) 中的 cars 屬性進行對應 -->
< collection property = "cars" column = "id" select ="org.leadfar.mybatis.Car.selectByPerson" ></ collection >
</ resultMap >