【Java】MyBatis框架初步學習總結


  本篇篇幅較長,請善用 Ctrl + F 搜索功能。

  結尾補充了 MyBatis 中 resultMap 的映射級別。

----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 

  MyBatis學完也有幾天了,總結一下學習到的內容,也算是復習了。

 

  使用MyBatis之前,我們要知道,什么是MyBatis?

  MyBatis是apache一個開源的,基於Java的持久層框架。

  MyBatis的優點有哪些?

  學習簡單,提供半自動的關系映射,SQL語句與代碼分離。

  MyBatis的缺點又有哪些?

  要會寫SQL語句;每個數據庫的SQL語句都多少會有偏差,所以不方便更換數據庫。

  MyBatis適合什么樣的項目?

  適合性能要求很高,或者需要變化較多的項目。

  

  要使用MyBatis,得有MyBatis的jar包。

  在https://github.com/mybatis/mybatis-3/releases下載mybatis-x.x.x.zip,我用的版本是3.3.2。

  壓縮包里的mybatis-x.x.x.jar就是我們要的jar包了,.pdf的是幫助文檔,lib文件夾里的是MyBatis的依賴包,具體作用自行百度,一起丟到項目的lib的文件夾里全部add build一下就行了。

  哦對了,jdbc的jar包請自行准備。

  

  只有jar包還不夠,我們還需要xml配置文件。

  新建一個Source Folder,將配置文件統一放在里面。為了方便識別,MyBatis的配置文件我們可以命名為“mybatis-config.xml”,配置文件的內容大致是這樣的,改改就能用:  

 1 <?xml version="1.0" encoding="UTF-8" ?>
 2 <!DOCTYPE configuration
 3 PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
 4 "http://mybatis.org/dtd/mybatis-3-config.dtd">
 5 <configuration>
 6     <properties resource="mybatis.properties" /><!-- jdbc配置文件 -->
 7     <typeAliases><!-- 類型別名 -->
 8         <typeAlias type="cn.bwm.pojo.User" alias="User"/><!-- 給指定的類起一個別名 -->
 9         <package name="cn.bwm.pojo" /><!-- 給包里的所有類起一個和類名一樣的別名 -->
10     </typeAliases>
11     <environments default="test"><!-- 配置環境 ,default選擇默認配置-->
12         <environment id="test"><!-- 環境元素 -->
13             <transactionManager type="JDBC" />    <!-- 配置事務管理器 -->
14             <dataSource type="POOLED"><!-- 數據源 -->
15                 <property name="driver" value="${driver}" /><!-- jdbc配置文件對應屬性 -->
16                 <property name="url" value="${url}" />
17                 <property name="username" value="${username}" />
18                 <property name="password" value="${password}" />
19             </dataSource>
20         </environment>
21     </environments>
22     <mappers><!-- 映射器 -->
23         <mapper resource="cn/bwm/dao/IUserMapper.xml" /><!-- xml映射文件 -->
24     </mappers>
25 </configuration>

  每個標簽的具體作用請參考官方文檔,中文的,http://www.mybatis.org/mybatis-3/zh/getting-started.html

  

  最后一步也是舉足輕重的一步,配置MyBatis的兩個dtd文件。

  這兩個文件,一個叫“mybatis-3-config.dtd”,另一個叫“mybatis-3-mapper.dtd”,我們可以通過解壓縮mybatis-x.x.x.jar,在\org\apache\ibatis\builder\xml 這個目錄下找到這兩個文件。

  我用的是MyEclipse10.6,配置的步驟是:

  Windows → Preferences ; 選擇XML Catalog ,選擇User Specified Entries,單擊 Add ; 單擊 File System 后選擇dtd文件, Key填寫 -//mybatis.org//DTD Config 3.0//EN (與MyBatis-config.xml文件投中的 -//mybatis.org//DTD Config 3.0//EN 相同)。

  兩個dtd文件配置步驟一樣,配置完成以后,在MyBatis-config.xml文件和xml映射文件中就可以使用 alt + / 自動聯想了。

  
  完成以上步驟以后,MyBatis就算是部署到項目中了,至於如何使用MyBatis,我們還需要准備一個數據庫。這個數據庫至少要有兩張結構簡單有主外鍵關系的表,以及少量數據。在項目中創建與數據庫的表對應的實體類,在數據訪問層創建實體類對應的接口,並聲明抽象方法,例如:

/**
 * 老師類
 * @author Administrator
 *
 */
public class Teacher {
    private int id;
    private String name;
    private Student student;
    private List<Student> studentList;
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Student getStudent() {
        return student;
    }
    public void setStudent(Student student) {
        this.student = student;
    }
    public List<Student> getStudentList() {
        return studentList;
    }
    public void setStudentList(List<Student> studentList) {
        this.studentList = studentList;
    }
}

/**
 * 學生類
 * @author Administrator
 *
 */
public class Student {
    private int id;
    private String name;
    private int tid;
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getTid() {
        return tid;
    }
    public void setTid(int tid) {
        this.tid = tid;
    }    
}

/**
 * Teacher實體類的對應接口
 * @author Administrator
 *
 */
public interface ITeacherMapper {
    /**
     * 根據id查詢老師
     * @param id
     * @return    Teacher對象
     */
    public Teacher queryTeacherById(int id);
}

  在接口的同目錄下創建同名xml文件:

1 <?xml version="1.0" encoding="UTF-8" ?>
2 <!DOCTYPE mapper
3 PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
4 "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
5 <mapper namespace="cn.bwm.dao.ITeacherMapper">
6     <select id="queryTeacherById" parameterType="int" resultType="Teacher">
7         SELECT `Id`,`Name` FROM `teacher` WHERE `Id` = #{id}
8     </select>
9 </mapper>

  寫完這些代碼和配置文件,現在,我們再來簡單了解一下MyBatis的核心接口和類:

  • SqlSessionFactoryBuilder:提供多個build()方法的重載,只負責構建SqlSessionFactory的對象,只需要使用一次。
  • SqlSessionFactory:提供OpenSession()方法的重載,用來創建SqlSession對象,需要使用多次。
  • SqlSession:用於執行已映射的SQL語句,在未使用close()方法關閉前可多次使用SQL。

  深入了解請查看官方文檔,中文的, http://www.mybatis.org/mybatis-3/zh/java-api.html 。

  根據三個核心接口和類,我們再寫一個用來獲取SqlSession對象的工具類:

 1 public class SqlSessionUtil {
 2     private static SqlSessionFactory sqlSessionFactory;
 3     
 4     static{
 5         SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
 6         try {
 7             InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
 8             sqlSessionFactory = sqlSessionFactoryBuilder.build(inputStream);
 9         } catch (IOException e) {
10             e.printStackTrace();
11         }
12     }
13     
14     /**
15      * 獲取SqlSession對象
16      * @return
17      */
18     public static SqlSession getSqlSession(){
19             return sqlSessionFactory.openSession();        
20     }
21     
22     /**
23      * 關閉SqlSession對象
24      * @param sqlSession
25      */
26     public static void closeSqlSession(SqlSession sqlSession){
27         if (sqlSession != null) {
28             sqlSession.close();
29         }
30     }
31 }

  現在,我們可以寫測試代碼了:

1 public class Test {
2     public static void main(String[] args) {
3         SqlSession sqlSession = SqlSessionUtil.getSqlSession();
4         Teacher teacher = sqlSession.getMapper(ITeacherMapper.class).queryTeacherById(1);
5         System.out.println("編號:" + teacher.getId() + "\t姓名:" + teacher.getName());
6         SqlSessionUtil.closeSqlSession(sqlSession);
7     }
8 }

  相信大家也看出來了,我們使用MyBatis執行了簡單的查詢操作,並將結果封裝成了一個對象,而這其中的關鍵就在於與接口同名的xml映射文件。

  我們來看一下映射文件中用到了哪些元素:

  • mapper標簽:映射文件的根節點。
    • namespace屬性:用於區分不同的napper,全局唯一,必須與對應的接口同名。
  • select標簽:映射查詢語句。
    • id屬性:命名空間中唯一的標識符,與接口中的方法名對應。
    • parameterType:表示傳入參數的類型的完全限定名或別名。完全限定名就是 java.long.String 這樣的完整路徑,別名則是在 mybatis-config.xml 中設置的別名,MyBatis已經為部分Java類型提供了別名。可以省略(省略好像也沒有什么影響)
    • resultType:查詢語句返回結果類型的完全限定名或別名。在這里我寫的是 Teacher ,MyBatis就會按照查詢的結果的列名和類的屬性字段進行匹配映射,一樣的就調用set方法進行賦值,所以類的屬性要盡量和數據庫的字段名一樣,否則就要在查詢的時候給查詢結果起別名。如果想返回 int 或 String ,可以使用MyBatis提供的別名。如果方法想返回一個List集合,這里寫List集合里元素的類型。
  • #{id}:這就告訴 MyBatis 創建一個預處理語句參數,通過 JDBC,這樣的一個參數在 SQL 中會由一個“?”來標識,並被傳遞到一個新的預處理語句中。實際上,無論MyBatis的入參是哪種參數類型,都會被放在一個Map中,單參數入參就會有這些情況 
    • 基本類型:對應接口中方法的參數名作為 key , 變量值為 value。
    • 對象:對象的屬性名作為 key,屬性值為 value。
    • List:默認 list 作為 key,該 list 即為 value。
    • 數組:默認 array 作為 key,該數組即為 value。
    • Map:鍵值不變。

  我們在查詢的時候,不可能只有單參數查詢,而parameterType只能寫一個類型,這個時候,有三種方法:

  1. 使用對象作為參數。
  2. 將參數封裝成Map集合。
  3. 使用@Param注解。

  先說第一種,使用對象作為參數。這種方法應該比較適合插入操作,我們這里強行使用一波。

  先在接口里寫上方法:

1 /**
2      * 根據編號和姓名查詢老師
3      * @param t Teacher對象
4      * @return    Teacher對象
5      */
6     public Teacher queryTeacherByIdName(Teacher t);

  在xml映射文件里寫對應的SQL語句,parameterType寫的是參數類型 Teacher,#{id}和#{name}都是 Teacher 類的屬性,CONCAT()是MySQL的函數,用來拼接字符串:

1 <select id="queryTeacherByIdName" parameterType="Teacher" resultType="Teacher">
2     SELECT  `Id`,`Name` FROM `teacher` WHERE `Id` = #{id} AND `Name` LIKE CONCAT('%' , #{name} , '%')
3 </select>

  測試代碼是這樣的:

1     public static void main(String[] args) {
2         SqlSession sqlSession = SqlSessionUtil.getSqlSession();
3         Teacher t = new Teacher();
4         t.setId(1);
5         t.setName("小");
6         Teacher teacher = sqlSession.getMapper(ITeacherMapper.class).queryTeacherByIdName(t);
7         System.out.println("編號:" + teacher.getId() + "\t姓名:" + teacher.getName());
8         SqlSessionUtil.closeSqlSession(sqlSession);
9     }

  這樣便完成了使用對象作為參數來進行查詢的操作。

  然后是第二種,將參數封裝成Map集合,我們修改一下剛才的方法,把參數改成 Map<String , Object>集合:

1     /**
2      * 根據編號和姓名查詢老師
3      * @param map Map<String,Object>集合
4      * @return    Teacher對象
5      */
6     public Teacher queryTeacherByIdName(Map<String,Object> map);

  xml映射文件里,parameterType改成了 map,是MyBatis提供的別名:

1     <select id="queryTeacherByIdName" parameterType="map" resultType="Teacher">
2         SELECT  `Id`,`Name` FROM `teacher` WHERE `Id` = #{id} AND `Name` LIKE CONCAT('%' , #{name} , '%')
3     </select>

  測試代碼把剛才作為參數的 Teacher 對象改成 Map<String , Object>集合:

1     public static void main(String[] args) {
2         SqlSession sqlSession = SqlSessionUtil.getSqlSession();
3         Map<String,Object> map = new HashMap<String,Object>();
4         map.put("id", 1);
5         map.put("name", "小");
6         Teacher teacher = sqlSession.getMapper(ITeacherMapper.class).queryTeacherByIdName(map);
7         System.out.println("編號:" + teacher.getId() + "\t姓名:" + teacher.getName());
8         SqlSessionUtil.closeSqlSession(sqlSession);
9     }

  這樣就完成了使用 Map 傳遞多個參數。

  最后是第三種,使用@Param注解,還是直接修改剛才的方法,把 Map<String , Object> 換成 @Param 注解的參數:

1     /**
2      * 根據編號和姓名查詢老師
3      * @param id    編號
4      * @param name    姓名
5      * @return    Teacher 對象
6      */
7     public Teacher queryTeacherByIdName(@Param("tid")int id , @Param("tname")String name);

  xml文件里,因為@Param("")里寫的是 tid 和 tname,所以 #{} 也要寫的一樣:

1     <select id="queryTeacherByIdName" parameterType="map" resultType="Teacher">
2         SELECT  `Id`,`Name` FROM `teacher` WHERE `Id` = #{tid} AND `Name` LIKE CONCAT('%' , #{tname} , '%')
3     </select>

  測試代碼里,參數也不用放在 Map 集合里了:

1     public static void main(String[] args) {
2         SqlSession sqlSession = SqlSessionUtil.getSqlSession();
3         Teacher teacher = sqlSession.getMapper(ITeacherMapper.class).queryTeacherByIdName(1 , "小");
4         System.out.println("編號:" + teacher.getId() + "\t姓名:" + teacher.getName());
5         SqlSessionUtil.closeSqlSession(sqlSession);
6     }

  這就是 @Param 的使用方法。

  三種方法說完了,但不管參數有多少,我們現在查詢的結果都只是一個簡單對象,如果結果的類型包含另一個類型,或者包含一個集合,這里我們就要了解一下 <resultMap> 元素及其子元素 <result>、<association> 和 <conllection> 。

  我們通過代碼來講解這幾個個元素的使用方法,我的 Teacher 類中已經有一個 Student 屬性和一個 List<Student> 屬性:

 1 /**
 2  * 老師類
 3  * @author Administrator
 4  *
 5  */
 6 public class Teacher {
 7     private int id;
 8     private String name;
 9     private Student student;    //學生對象
10     private List<Student> studentList;    //學生集合
11     //省略 getset 方法
12 }

  接口里的方法可以不用修改,xml映射文件需要大改一下:

 1     <select id="queryTeacherByIdName" resultMap="query">
 2         select t.`Id` as tid , t.`Name`as tname , s.`Id` as sid , s.`Name` as sname from `teacher` as t 
 3         inner join `student` as s on s.`Tid` = t.`Id` where t.`Id` = #{tid}
 4     </select>    
 5     <resultMap type="Teacher" id="query">
 6         <id column="tid" property="id"/>
 7         <result column="tname" property="name"/>
 8         <association property="student" javaType="Student">
 9             <id column="sid" property="id"/>
10             <result column="sname" property="name"/>
11             <result column="tid" property="tid"/>
12         </association>
13         <collection property="studentList" ofType="Student">
14             <id column="sid" property="id"/>
15             <result column="sname" property="name"/>
16             <result column="tid" property="tid"/>
17         </collection>
18     </resultMap>

  select 標簽的 resultType 屬性換成了 resultMap屬性,值與 resultMap 標簽的 id 一樣。

  • resultMap標簽:用來自定義結果映射,通常在實體類的屬性名與數據庫里表的字段不一致導致無法自動映射時,以及需要映射復雜對象時使用。要注意的是,resultMap 和 resultType 這兩個元素只能使用其中一個,不能同時存在。
    • id屬性:resultMap 的唯一標識。
    • type屬性:表示該 resultMap 的映射結果類型。
  • id 標簽:用來標記主鍵,可以提高整體性能。
    • column 屬性:對應SQL語句查詢結果的字段名。
    • property 屬性:對應要賦值的屬性。
  • result 標簽:標志簡單屬性。
  • association 標簽:用來映射 JavaBean 的某個 復雜類型 屬性,僅處理一對一的關聯關系。
    • javaType 屬性:完整 Java 類名或者別名。
  • collection 元素:映射 JavaBean 的某個 復雜類型 的集合屬性,用來處理一對多的關聯關系。
    • ofType 屬性:完整 Java 的類名或或別名,即集合所包含的類型。

  另外,resultMap 結果映射可以復用,我們改一下xml映射文件的代碼:

 1     <select id="queryTeacherByIdName" resultMap="query1">
 2         select t.`Id` as tid , t.`Name`as tname , s.`Id` as sid , s.`Name` as sname from `teacher` as t 
 3         inner join `student` as s on s.`Tid` = t.`Id` where t.`Id` = #{tid}
 4     </select>    
 5         
 6     <resultMap type="Student" id="student">
 7             <id column="sid" property="id"/>
 8             <result column="sname" property="name"/>
 9             <result column="tid" property="tid"/>
10     </resultMap>
11     
12     <resultMap type="Teacher" id="query1">
13         <id column="tid" property="id"/>
14         <result column="tname" property="name"/>
15         <association resultMap="student" property="student" javaType="Student"/>
16     </resultMap>
17     
18     <resultMap type="Teacher" id="query2">
19         <id column="tid" property="id"/>
20         <result column="tname" property="name"/>
21         <collection resultMap="student" property="studentList" ofType="Student"/>
22     </resultMap>

  在代碼里,兩個 resultMap 里的 association 和 collection 都重用了 query 這個 resultMap ,可以節省不少代碼。順便一提,我在測試時,association 和 collection 無法在一個 resultMap 里重用同一個 resultMap ,collection 會失效,最終查詢出來的結果,List的元素數量是0,具體原因暫時還沒找到。

  

  查詢部分算是結束了,接下是比較簡單的增刪改操作,先在接口里寫上對應的方法:

 1     /**
 2      * 增加老師
 3      * @param teacher    Teacher對象
 4      * @return
 5      */
 6     public int addTeacher(Teacher teacher);
 7     
 8     /**
 9      * 修改老師
10      * @param teacher    Teacher對象
11      * @return
12      */
13     public int updateTeacher(Teacher teacher);
14     
15     /**
16      * 根據id刪除老師
17      * @param id    老師的編號
18      * @return
19      */
20     public int deleteTeacher(int id);

  xml映射文件里也要使用對應的標簽,分別是 <insert>、<update>和<delete>

 1     <insert id="addTeacher" parameterType="Teacher">
 2         INSERT INTO `teacher`(`Name`) VALUES(#{name})
 3     </insert>
 4     
 5     <update id="updateTeacher" parameterType="Teacher">
 6         UPDATE `teacher` SET `Name` = #{name} WHERE id = #{id}
 7     </update>
 8     
 9     <delete id="deleteTeacher" parameterType="int">
10         DELETE FROM `teacher` WHERE `Id` = #{id}
11     </delete>

  因為增刪改的操作返回的是數據庫受影響的行數,所以這個三個標簽是沒有 resultType 和 resultMap 兩個屬性的。

  測試部分需要增加一點點代碼:

 1     /**
 2      * 添加老師
 3      */
 4     private static void addTeacher() {
 5         SqlSession sqlSession = SqlSessionUtil.getSqlSession();
 6         Teacher teacher = new Teacher();
 7         teacher.setName("小黑白");
 8         int result = sqlSession.getMapper(ITeacherMapper.class).addTeacher(teacher);
 9         if (result > 0) {
10             sqlSession.commit();    //提交事務
11             System.out.println("添加成功!");
12         }else{
13             System.out.println("添加失敗!");
14         }
15         SqlSessionUtil.closeSqlSession(sqlSession);
16     }
17 
18     /**
19      * 修改老師
20      */
21     private static void updateTeacher() {
22         SqlSession sqlSession = SqlSessionUtil.getSqlSession();
23         Teacher teacher = new Teacher();
24         teacher.setId(2);
25         teacher.setName("小黑");
26         int result = sqlSession.getMapper(ITeacherMapper.class).updateTeacher(teacher);
27         if (result > 0) {
28             sqlSession.commit();    //提交事務
29             System.out.println("修改成功!");
30         }else{
31             System.out.println("修改失敗!");
32         }
33         SqlSessionUtil.closeSqlSession(sqlSession);
34     }
35     
36     /**
37      * 根據id刪除老師
38      */
39     private static void deleteTeacher() {
40         SqlSession sqlSession = SqlSessionUtil.getSqlSession();
41         int result = sqlSession.getMapper(ITeacherMapper.class).deleteTeacher(2);
42         if (result > 0) {
43             sqlSession.commit();    //提交事務
44             System.out.println("刪除成功!");
45         }else{
46             System.out.println("刪除失敗!");
47         }
48         SqlSessionUtil.closeSqlSession(sqlSession);
49     }

  這三個操作都有一個共同的特點,就是在判斷數據庫受影響的行數大於0以后,都會調用 SqlSession 的 commit() 方法。

  這是因為 MyBatis 在執行增刪改操作的時候並沒有直接操作數據庫,我們可以理解成是在操作一個虛擬的數據庫,當我們調用 commit() 方法后,我們所做的操作才會對真正的數據庫產生影響。

  以上就是使用 MyBatis 對數據庫進行增刪改查操作的示例,我們不難發現,把 SQL語句寫在 xml映射文件里會導致我們無法用代碼改變 SQL 語句,顯得不夠靈活,對此,MyBatis為我們提供了動態SQL

  

  動態SQL是MyBatis的一個強大的特性,基於 OGNL 的表達式,使我們可以方便的動態改變 SQL 語句。

  用於動態SQL的元素有:

  • if
  • choose(when , otherwise)
  • trim(where , set)
  • foreach

  假設,我們使用 id 和 name 來查詢老師,如果 name 沒有傳入參數,就只用 id 查詢老師,這時候就可以使用 if 來進行判斷

1     <select id="queryTeacher" parameterType="map" resultType="Teacher">
2         SELECT * FROM `teacher`
3         WHERE `Id` = #{id}
4         <if test="name != null and name != ''">
5             AND `Name` LIKE CONCAT('%' , #{name} , '%')
6         </if>
7     </select>

  test 屬性其他標簽也有,用來判斷條件。

  再假設,id 和 name 只要有其中一個就可以了,按照有條件進行查詢,如果沒有就查詢全部,這時可以使用 choose 和 它的子元素 when、otherwise來實現:

 1     <select id="queryTeacher" parameterType="map" resultType="Teacher">
 2         SELECT * FROM `teacher`
 3         WHERE 
 4         <choose>
 5             <when test="id != null and id != 0">
 6                 `Id` = #{id}
 7             </when>
 8             <when test="name != null and name != ''">
 9                 `Name` = #{name}
10             </when>
11             <otherwise>
12                 1 = 1
13             </otherwise>
14         </choose>
15     </select>

  choose 相當於 Java 中的 switch 語句,從上向下開始判斷,只要有 when 的 test 成立,就返回該 when 里的 SQL 語句並跳出 choose,如果所有的 when 都不成立,就返回 otherwise 里的SQL語句。因為是從上向下判斷的,所以要注意 SQL 語句的優先順序。

  還有最后的 otherwise 里的 1 = 1,如果沒有這個的話,很有可能因為 id 和 name 兩個都沒有參數而造成 where 后面什么都沒有,造成 SQL 語句報錯。這時,就需要使用 trim元素,它可以靈活的去除多余的關鍵字

 1     <select id="queryTeacher" parameterType="map" resultType="Teacher">
 2         SELECT * FROM `theacher`
 3         <trim prefix="WHERE" prefixOverrides="and | or">
 4             <if test="id != null and id != 0">
 5                 AND `id` = #{id}
 6             </if>
 7             <if test="name != null and name != ''">
 8                 AND `name` = #{name}
 9             </if>
10         </trim>
11     </select>

  trim 元素會自動識別標簽內是否有返回值,有的話就在內容的前面加上 prefix 屬性的值 where,並忽略 prefixOverrides 里所包含的內容 and 和 or 。(這部分代碼只為了展示 trim 的作用,請忽略代碼的意義)

  這部分的 trim 的使用等價於 where 標簽:

 1     <select id="queryTeacher" parameterType="map" resultType="Teacher">
 2         SELECT * FROM `theacher`
 3         <where>
 4             <if test="id != null and id != 0">
 5                 AND `id` = #{id}
 6             </if>
 7             <if test="name != null and name != ''">
 8                 AND `name` = #{name}
 9             </if>
10         </where>
11     </select>

  trim 不僅可以在 SQL 語句前添加內容和忽略內容,也可以在 SQL 語句后追加內容和忽略內容,例如剛才的修改操作:

 1     <update id="updateTeacher" parameterType="Teacher">
 2         UPDATE `teacher` SET `Name` = #{name} WHERE id = #{id}
 3         <trim prefix="Set" suffixOverrides="," suffix="WHERE id = #{id}">
 4             <if test="id != null">
 5                 `id` = #{id} ,
 6             </if>
 7             <if test="name != null">
 8                 `name` = #{name} ,
 9             </if>
10         </trim>
11     </update>

  使用 prefix 在 SQL 語句前加上 prefix 的值 Set, 在 SQL 語句的最后加上 suffix 的值 WHERE id = #{id},忽略 SQL 語句最后的 suffixOverrides 的值  , 。(這段代碼只展示了 trim 的作用,請無視不合理的部分)

  這部分 trim 的使用等價於 set 標簽:

 1     <update id="updateTeacher" parameterType="Teacher">
 2         UPDATE `teacher` SET `Name` = #{name} WHERE id = #{id}
 3         <set>
 4             <if test="id != null">
 5                 `id` = #{id} ,
 6             </if>
 7             <if test="name != null">
 8                 `name` = #{name} ,
 9             </if>
10         </set>
11         WHERE `id` = #{id}
12     </update>

  不過 WHERE 需要自己寫。

  另外,prefix、perfixOverriders、suffix 和 suffixOverriders四個屬性是可以同時使用的,根據時間情況選擇。

  foreach 元素,用於循環集合,主要用於構建 IN 條件語句的時候使用

1     <select id="queryTeacher" resultType="Teacher">
2         SELECT * FROM `theacher`
3         WHERE `id` IN 
4         <foreach collection="list" item="id" index="index" open="(" separator="," close=")">
5             #{id}
6         </foreach>
7     </select>

  這里我們迭代了 list 集合,collection 屬性表示迭代時每個元素的別名;index 表示每次迭代到的位置;open 表示 SQL 語句以什么開始;separator 表示每次迭代直接用什么進行分隔;close 表示 SQL 語句以什么結束;collection 必須指定,對應要遍歷的集合。

  在遍歷 對象 和 數組時,index 表示當前迭代的次數,item 的值是表示當前迭代獲取的元素。

  遍歷 Map 時,index 是鍵, item 是值。

 

  補充一下 resultMap 的映射級別

  我在使用 resultMap 自定義映射結果的時候發現,即使我只在 resultMap 里定義一個 id ,其他的屬性也還是會自動映射上去。

  這是因為 MyBatis 的配置文件中,autoMappingBehavior 的默認級別是 PARTIAL,只會自動映射沒有定義嵌套結果集映射的結果集,改成 NONE 就可以取消自動映射,改成FULL的話,會自動映射復雜的結果集,無論是否嵌套。

  
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

  到這里,關於MyBatis我所學習到的內容就全部結束了。

  第一次寫博客沒有經驗,寫的很長,也很爛

  感謝耐心看到這里的你,如果對你有所幫助就再好不過了


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM