Java Persistence with MyBatis 3讀書筆記

第一章 mybatis 簡介

如下內容是本身在看本書時以爲重要的地方記錄下來,一方面本身作個筆記也但願對其餘同行有幫助java

簡介

mybatis: 是一個簡化和實現了Java數據持久層的開源框架愛,抽象和大量的jdbc冗餘代碼,提供簡單的API和數據庫加護mysql

mybatis優勢

  1. 消除大量的JDBC冗餘代碼算法

  2. 低的學習曲線spring

  3. 很好的域傳統數據庫協做sql

  4. 接收SQL語句數據庫

  5. 提供Spring框架集成apache

  6. 提供第三方緩存類庫集成緩存

  7. 引入更好的性能安全

mybatis簡單使用

  1. 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>
      <typeAliases>
    <typeAlias alias="Student" type="com.mybatis3.domain.Student" />
      </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:3306/test" />
        <property name="username" value="root" />
        <property name="password" value="admin" />
      </dataSource>
    </environment>
      </environments>
      <mappers>
    <mapper resource="com/mybatis3/mappers/StudentMapper.xml" />
      </mappers>
    </configuration>

0.1. 建立session Factory 類

package com.mybatis3.util;
import java.io.*;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.*;
public class MyBatisSqlSessionFactory
{
private static SqlSessionFactory sqlSessionFactory;
public static SqlSessionFactory getSqlSessionFactory()
{
    if(sqlSessionFactory == null)
    {
        InputStream inputStream;
try
        {
            inputStream = Resources.
                          getResourceAsStream("mybatis-config.xml");
            sqlSessionFactory = new
            SqlSessionFactoryBuilder().build(inputStream);
        }
        catch (IOException e)
        {
            throw new RuntimeException(e.getCause());
         }
    }
    return sqlSessionFactory;
}
public static SqlSession openSession()
{
    return getSqlSessionFactory().openSession();
}
}
  1. 建立xml映射

    <select id="findStudentById" parameterType="int" resultType="Student">
    SELECT STUD_ID AS studId, NAME, EMAIL, DOB
        FROM STUDENTS WHERE STUD_ID=#{Id}
    </select>
    <insert id="insertStudent" parameterType="Student">
    INSERT INTO STUDENTS(STUD_ID,NAME,EMAIL,DOB)
        VALUES(#{studId},#{name},#{email},#{dob})
    </insert>
  2. 建立mapper接口

    public interface StudentMapper
    {
        Student findStudentById(Integer id);
        void insertStudent(Student student);
    }
  3. 建立會話使用接口

    SqlSession session = getSqlSessionFactory().openSession();
    StudentMapper mapper = session.getMapper(StudentMapper.class);
    // Select Student by Id
    Student student = mapper.selectStudentById(1);
    //To insert a Student record
    mapper.insertStudent(student);

第二章 mybatis 配置

使用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>
    //加載properties文件
  <properties resource="application.properties">
    <property name="username" value="db_user" />
    <property name="password" value="verysecurepwd" />
  </properties>
  //開啓緩存
  <settings>
    <setting name="cacheEnabled" value="true" />
  </settings>
  
  //別名
  <typeAliases>
    <typeAlias alias="Tutor" type="com.mybatis3.domain.Tutor" />
    <package name="com.mybatis3.domain" />
  </typeAliases>  
  
  //類型處理器,註冊自定義類型
  <typeHandlers>
    <typeHandler handler="com.mybatis3.typehandlers.PhoneTypeHandler" />
    <package name="com.mybatis3.typehandlers" />
  </typeHandlers>
  
  //支持配置多個數據源,設置默認環境爲開發環境
  <environments default="development">
    <environment id="development">
      <transactionManager type="JDBC" />
      <dataSource type="POOLED">
        <property name="driver" value="${jdbc.driverClassName}" />
        <property name="url" value="${jdbc.url}" />
        <property name="username" value="${jdbc.username}" />
        <property name="password" value="${jdbc.password}" />
      </dataSource>
    </environment>
     <environment id="production">
      <transactionManager type="MANAGED" />
      <dataSource type="JNDI">
        <property name="data_source" value="java:comp/jdbc/MyBatisDemoDS" />
      </dataSource>
    </environment>
  </environments>
  <mappers>
    <mapper resource="com/mybatis3/mappers/StudentMapper.xml" />
    <mapper url="file:///D:/mybatisdemo/mappers/TutorMapper.xml" />
    <mapper class="com.mybatis3.mappers.TutorMapper" />
  </mappers>
</configuration>

以上是一個簡單的基於XML的配置
經過以上XML能夠到全部的配置:

  1. 加載properties 文件

    • 直接默認值

      <properties resource="application.properties">
            <property name="jdbc.username" value="db_user" />
            <property name="jdbc.password" value="verysecurepwd" />
      </properties>

      若是文件中定義了jdbc.username,以上配置中的默認值會被覆蓋掉

    • 經過佔位符

      <property name="driver" value="${jdbc.driverClassName}" />
        <property name="url" value="${jdbc.url}" />
  2. 開啓緩存

  3. 配置environments default="development" 實現默認環境 ,能夠配置不一樣環境

  4. 配置多數據庫實現

  5. 針對不一樣的數據庫建立不一樣sessionFactory

    InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
    SqlSessionFactory defaultSqlSessionFactory = new SqlSessionFactoryBuilder().
    build(inputStream);
    SqlSessionFactory cartSqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStre
        am, "shoppingcart");
    reportSqlSessionFactory = new SqlSessionFactoryBuilder().
    build(inputStream, "reports");

    若是不指定環境id,則使用默認的環境建立

  6. 數據庫類型配置

    • UNPOOLED

      mybatis會爲每一個數據庫建立錯誤一個新的鏈接,並關閉它。__只適用於小閨蜜數據併發__
    • POOLED

      mybatis建立一個數據庫鏈接池,__開發環境常用__  
      默認的數據庫鏈接池實現是經過`org.apache.ibatis.datasource.pooled.PooledDataSource`
    • JNDI

      mybatis從應用服務器配置好的JNDI數據源獲取數據庫鏈接
  7. 事務管理

    • JDBC

      是由JDBC事務管理器管理事務。 內部將經過JDBCTransactionFactory建立事務管理
    • MANAGED

      應用服務器負責管理數據庫鏈接生命週期使用。內部使用`ManagedTranscationFactory`類來建立事務管理器
  8. 設置別名
    因爲在* mapper.xml 文件中resultTypeparameterType屬性設置要使用全限定名,可使用別名的形式簡化

    <typeAliases>
          <typeAlias alias="Student" type="com.mybatis3.domain.Student" />
          <typeAlias alias="Tutor" type="com.mybatis3.domain.Tutor" />
          <package name="com.mybatis3.domain" />
    </typeAliases>

    也能夠不用直接設定別名,能夠設定包,而後系統自動掃描設置一個以類首字母小寫的別名
    經過實體類添加註解形式實現

    @Alias("")
    public class Student{
    
    }
  9. 類型處理器
    mubatis對一下類型實現內建處理器 :

    • 全部基本數據類型

    • 基本類型的包裹類型(裝箱操做對象類型)

    • byte[]

    • java.util.Date

    • java.sql.Date

    • java.sql.Time

    • java.sql.Timestamp

    • java枚舉類型

    建立自定義的類型處理器,處理自定義類型

    //PhoneNumber 自定義的類
    public class PhoneTypeHandler extends BaseTypeHandler<PhoneNumber>
    {
         @Override
    public void setNonNullParameter(PreparedStatement ps, int i,
                                    PhoneNumber parameter, JdbcType jdbcType) throws SQLException
    {
        ps.setString(i, parameter.getAsString());
    }
    
    public PhoneNumber getNullableResult(ResultSet rs, String columnName)  throws SQLException
    {
         return new PhoneNumber(rs.getString(columnName));
    }
    
    public PhoneNumber getNullableResult(ResultSet rs, int columnIndex) throws SQLException
    {
         return new PhoneNumber(rs.getString(columnIndex));
    }
    }

    別忘了註冊

  10. 全局參數設定(一下是默認的,)

    <settings>
               <setting name="cacheEnabled" value="true" />
               <setting name="lazyLoadingEnabled" value="true" />
               <setting name="multipleResultSetsEnabled" value="true" />
               <setting name="useColumnLabel" value="true" />
               <setting name="useGeneratedKeys" value="false" />
               <setting name="autoMappingBehavior" value="PARTIAL" />
               <setting name="defaultExecutorType" value="SIMPLE" />
               <setting name="defaultStatementTimeout" value="25000" />
               <setting name="safeRowBoundsEnabled" value="false" />
               <setting name="mapUnderscoreToCamelCase" value="false" />
               <setting name="localCacheScope" value="SESSION" />
                  <setting name="jdbcTypeForNull" value="OTHER" />
                  <setting name="lazyLoadTriggerMethods" value="equals,clone,hashCode ,toString" />
    </settings>
  11. 配置mappers映射xml文件路徑
    多種配置形式

    <mappers>
        <mapper resource="com/mybatis3/mappers/StudentMapper.xml" /> 
        <mapper url="file:///D:/mybatisdemo/app/mappers/TutorMapper.xml" /> 
        <mapper class="com.mybatis3.mappers.TutorMapper" />
        <package name="com.mybatis3.mappers" />
    </mappers>

使用Java 配置

經過XML配置形式瞭解了mybatis中的各個配置屬性, 經過Java API 的配置形式也能夠實現

public class MybatisConfig{
    public static SqlSessionFactory getSqlSessionFactory()
    {
      SqlSessionFactory sqlSessionFactory = null;
    try
    {
        DataSource dataSource = DataSourceFactory.getDataSource();
        TransactionFactory transactionFactory = new
        JdbcTransactionFactory();
        Environment environment = new Environment("development",
                transactionFactory, dataSource);
        Configuration configuration = new Configuration(environment);
        configuration.getTypeAliasRegistry().registerAlias("student",
                Student.class);
        configuration.getTypeHandlerRegistry().register(PhoneNumber.
                class, PhoneTypeHandler.class);
        configuration.addMapper(StudentMapper.class);
        //建立
        sqlSessionFactory = new SqlSessionFactoryBuilder().
        build(configuration);
    }
    catch (Exception e)
    {
        throw new RuntimeException(e);
    }
    return sqlSessionFactory;
}
}

建立datasource

public class DataSourceFactory
{
    public static DataSource getDataSource(){
       String driver = "com.mysql.jdbc.Driver";
        String url = "jdbc:mysql://localhost:3306/mybatisdemo";
        String username = "root";
        String password = "admin";
        PooledDataSource dataSource = new PooledDataSource(driver, url,
        username, password);
        return dataSource;
    }
    
    //經過JNDI建立  
    public static DataSource getDataSource(){
        String jndiName = "java:comp/env/jdbc/MyBatisDemoDS";
        try{
                 InitialContext ctx = new InitialContext();
                DataSource dataSource = (DataSource) ctx.lookup(jndiName);
                return dataSource;
        }catch(NamingException e){
            throw new RuntimeException(e);
        }
    }
    
     
}

自定義mybatis日誌

mybatis 日誌支持

mybatis中針對日誌支持的優先級:

  • SLF4J

  • Apache Commons Logging

  • Log4j 2

  • Log4j

  • JDK logging

mybatis 設置日誌

調用一下方式實現

org.apache.ibatis.logging.LogFactory.useSlf4jLogging(); 
org.apache.ibatis.logging.LogFactory.useLog4JLogging();
org.apache.ibatis.logging.LogFactory.useLog4J2Logging(); 
org.apache.ibatis.logging.LogFactory.useJdkLogging();
org.apache.ibatis.logging.LogFactory.useCommonsLogging(); 
org.apache.ibatis.logging.LogFactory.useStdOutLogging();

第三章 XML配置SQL映射器

經過xml的形式映射有兩種形式:

  • 只有XML映射

    • 定義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">
        <mapper namespace="com.mybatis3.mappers.StudentMapper">
            <select id="findStudentById" parameterType="int" resultType="Student"> select stud_id as studId, name, email, dob
from Students where stud_id=#{studId}
              </select>
        </mapper>
  • 調用

    public Student = findStudentById(Integer id){
        SqlSession session = MybatisUtil.geSqlSession();
        try{
            //經過字符串的形式調用
            Student student = sqlSession.selectOne("com.mybatis3.mappers.StudentMapper.findStudentById",id);
        }
    }
  • 帶有mapper接口類形式

    須要注意的點: __其名空間namespace 應該跟StudentMapper接口的徹底限定名保持一至__, __ id,parameterType,returnType 應該分別和 StudentMapper 接口中的方法名, 參數類型,返回值相對應__

mybatis 提供的的映射語句

mybatis 提供多種不一樣的映射語句:

  • INSERT

    • useGeneratedKeys: 設置自增加

    • keyProperty: 主鍵屬性

  • SELECT

  • UPDATE

  • DELETE

mybatis 不一樣映射語句實例:

  1. INSERT

    • 經過自增加設置主鍵

      <insert id="insertStudent" parameterType="Student" useGeneratedKeys="true" keyProperty="studId">
          INSERT INTO STUDENTS(NAME, EMAIL, PHONE)
          VALUES(#{name},#{email},#{phone})
      </insert>
    • 針對支持序列生成主鍵值

      <insert id="insertStudent" parameterType="Student">
          <selectKey keyProperty="studId" resultType="int" order="BEFORE">
              SELECT ELEARNING.STUD_ID_SEQ.NEXTVAL FROM DUAL
          </selectKey>
          INSERT INTO STUDENTS(STUD_ID,NAME,EMAIL, PHONE)
          VALUES(#{studId},#{name},#{email},#{phone})
      </insert>
      
      //使用觸發器  
      <insert id="insertStudent" parameterType="Student">
          INSERT INTO STUDENTS(NAME,EMAIL, PHONE)
          VALUES(#{name},#{email},#{phone})
          <selectKey keyProperty="studId" resultType="int" order="AFTER">
              SELECT ELEARNING.STUD_ID_SEQ.CURRVAL FROM DUAL
          </selectKey>
      </insert>

mybatis結果集映射規則:

  • 對於 List, Collection, Iterable類型,返回 java.util.ArrayList

  • 對於Map 類型,返回 java.util.HashMap

  • 對於Set 類型: 返回 java.util.HashSet

  • 對於SortedSet類型: 返回java.util.TreeSet

mybatis 映射關係

一對一映射

  • 方式1: 使用點語法進行映射

public class Student
{
   private Integer studId;
   private String name;
   private String email;
   private Address address;        //一個地址對象, 每一個學生對應一個地址  
}

<resultMap type="Student" id="StudentWithAddressResult">
  <id property="studId" column="stud_id" />
  <result property="name" column="name" />
  <result property="email" column="email" />
  <result property="phone" column="phone" />
  <result property="address.addrId" column="addr_id" />
  <result property="address.street" column="street" />
  <result property="address.city" column="city" />
  <result property="address.state" column="state" />
  <result property="address.zip" column="zip" />
  <result property="address.country" column="country" />
</resultMap>
<select id="selectStudentWithAddress" parameterType="int"
resultMap="StudentWithAddressResult">
    SELECT STUD_ID, NAME, EMAIL, A.ADDR_ID, STREET, CITY, STATE,
        ZIP, COUNTRY
FROM STUDENTS S LEFT OUTER JOIN ADDRESSES A ON S.ADDR_ID=A.ADDR_ID
    WHERE STUD_ID=#{studId}
</select>
//使用了左外鏈接來查詢
  • 方式2: 使用嵌套結果 ResultMap進行映射

    • 引入其餘文件定義的ResultMap

      __使用標籤`association` 引入__
      <resultMap type="Address" id="AddressResult">
            <id property="addrId" column="addr_id" />
            <result property="street" column="street" />
            <result property="city" column="city" />
      </resultMap>
      
      <resultMap type="Student" id="StudentWithAddressResult">
            <id property="studId" column="stud_id" />
            <result property="name" column="name" />
            <result property="email" column="email" />
            <association property="address" resultMap="AddressResult" />
      </resultMap>
      查詢語句
      <select id="findStudentWithAddress" parameterType="int"
      resultMap="StudentWithAddressResult">
          SELECT STUD_ID, NAME, EMAIL, A.ADDR_ID, STREET, CITY, STATE, ZIP, COUNTRY
          FROM STUDENTS S LEFT OUTER JOIN ADDRESSES A ON S.ADDR_ID=A.ADDR_ID
          WHERE STUD_ID=#{studId}
      </select>
    • 自己內部嵌套

      <resultMap type="Student" id="StudentWithAddressResult">
            <id property="studId" column="stud_id" />
            <result property="name" column="name" />
            <result property="email" column="email" />
            <association property="address" javaType="Address">
              <id property="addrId" column="addr_id" />
              <result property="street" column="street" />
              <result property="city" column="city" />
              <result property="state" column="state" />
              <result property="zip" column="zip" />
              <result property="country" column="country" />
            </association>
      </resultMap>
  • 方式3: 使用其那套select查詢語句
    每個對應的對象實現本身的查詢語句

    <resultMap type="Address" id="AddressResult">
         <id property="addrId" column="addr_id" />
         <result property="street" column="street" />
    </resultMap>
    
    //查詢語句
    <select id="findAddressById" parameterType="int"
    resultMap="AddressResult">
    SELECT * FROM ADDRESSES WHERE ADDR_ID=#{id}
    </select>
    
    <resultMap type="Student" id="StudentWithAddressResult">
         <id property="studId" column="stud_id" />
        <association property="address" column="addr_id" select="findAddressById" />
    </resultMap>
    <select id="findStudentWithAddress" parameterType="int"
       resultMap="StudentWithAddressResult">
           SELECT * FROM STUDENTS WHERE STUD_ID=#{Id}
    </select>

    注意嵌套查詢:經過association 將另外一個對象的查詢語句嵌套進入, 而且此標籤好像只能用於查詢

一對一查詢中內部的對象在數據庫中對應的都是一個Id或者惟一標識值,因此此處底部的嵌套xml中的值都是id屬性的

一對多映射

使用<collection>元素將 一對多類型的結果 映射到 一個對象集合上

  1. 使用嵌套對象形式顯示

public class Tutor
{
    private Integer tutorId;
    private String name;
    private String email;
    private Address address;
    private List<Course> courses;
    / setters & getters
}
<resultMap type="Tutor" id="TutorResult">
  <id column="tutor_id" property="tutorId" />
  <result column="tutor_name" property="name" />
  <result column="email" property="email" />
  <collection property="courses" resultMap="CourseResult" />
</resultMap>


<select id="findTutorById" parameterType="int"
resultMap="TutorResult">
SELECT T.TUTOR_ID, T.NAME AS TUTOR_NAME, EMAIL, C.COURSE_ID,
C.NAME, DESCRIPTION, START_DATE, END_DATE
FROM TUTORS T LEFT OUTER JOIN ADDRESSES A ON T.ADDR_ID=A.ADDR_ID
LEFT OUTER JOIN COURSES C ON T.TUTOR_ID=C.TUTOR_ID
WHERE T.TUTOR_ID=#{tutorId}
</select>
  1. 使用嵌套語句實現

<resultMap type="Tutor" id="TutorResult">
  <id column="tutor_id" property="tutorId" />
  <result column="tutor_name" property="name" />
  <result column="email" property="email" />
  <association property="address" resultMap="AddressResult" />
  <collection property="courses" column="tutor_id" select="findCoursesByTutor" />
</resultMap>



<select id="findTutorById" parameterType="int" resultMap="TutorResult">
    SELECT T.TUTOR_ID, T.NAME AS TUTOR_NAME, EMAIL
    FROM TUTORS T WHERE T.TUTOR_ID=#{tutorId}
</select>
<select id="findCoursesByTutor" parameterType="int" resultMap="CourseResult">
  SELECT * FROM COURSES WHERE TUTOR_ID=#{tutorId}
</select>

注意: 嵌套 Select 語句查詢會致使 N+1 選擇問. 首先,主查詢將會執行(1 次),對於主 查詢返回的每一行,另一個查詢將會被執行(主查詢 N 行,則此查詢 N 次)。對於 大型數據庫而言,這會致使不好的性能問題。

動態SQL

mybatis 提供: <if>,<choose>,<where>,<foreach>,<trim> 進行構造動態SQL

1. if

<select id="searchCourses" parameterType="hashmap" resultMap="CourseResult"></select>
    SELECT * FROM COURSES
        WHERE TUTOR_ID= #{tutorId}
    <if test="courseName != null">
    AND NAME LIKE #{courseName}
    </if>
</select>

當if中test條件成立時, 纔會添加if中的內容到SQL語句中

choose, when, otherwise

<select id="searchCourses" parameterType="hashmap" resultMap="CourseResult">
    SELECT * FROM COURSES
    <choose>
        <when test="searchBy == 'Tutor'">
            WHERE TUTOR_ID= #{tutorId}
        </when>
        <when test="searchBy == 'CourseName'">
            WHERE name like #{courseName}
        </when>
        <otherwise>
            WHERE TUTOR start_date >= now()
        </otherwise>
    </choose>
</select>

__mybatis計算<choose> 測試條件的值,且使用第一個值爲true的子句, 若是沒有條件爲true,則使用<otherwise> 內的子句。

where

<select id="searchCourses" parameterType="hashmap"
resultMap="CourseResult">
    SELECT * FROM COURSES
    <where>
        <if test=" tutorId != null ">
            TUTOR_ID= #{tutorId}
        </if>
        <if test="courseName != null">
            AND name like #{courseName}
        </if>
        <if test="startDate != null">
            AND start_date >= #{startDate}
        </if>
        <if test="endDate != null">
            AND end_date <= #{endDate}
        </if>
    </where>
</select>

trim

<select id="searchCourses" parameterType="hashmap" resultMap="CourseResult">
     SELECT * FROM COURSES
<trim prefix="WHERE" prefixOverrides="AND | OR"> 
     <if test=" tutorId != null ">
         TUTOR_ID= #{tutorId}
     </if>  
     <if test="courseName != null">
        AND name like #{courseName}
     </if>
    </trim>
</select>

foreach

<select id="searchCoursesByTutors" parameterType="map"
resultMap="CourseResult">
SELECT * FROM COURSES
<if test="tutorIds != null">
<where>
<foreach item="tutorId" collection="tutorIds">
OR tutor_id=#{tutorId}
</foreach>
</where>
</if>
</select>

mybatis Other

處理枚舉

  1. 存儲枚舉名

    默認狀況下mybatis支持開箱方式持久化枚舉類型屬性, 其經過`EnumTypeHandler`來處理枚舉類型與Java類型對應  
    默認是使用字符串進行存儲的,數據表中對應的是枚舉對應的字符串
  2. 存儲枚舉對應的int類型值

    須要將枚舉對應的handler修改成如下類
    <typeHandler
    handler="org.apache.ibatis.type.EnumOrdinalTypeHandler"
    javaType="com.mybatis3.domain.Gender"/>
    __仍是建議使用默認的形式的,使用順序的若是改變了枚舉對應的順序,數據庫中值就沒法對應上了__

處理 blob類型

默認狀況下,mybatis將CLOB類型的列映射到 java.lang.String類型上,
將BLOB 映射到byte[]類型上

多個參數

  1. 使用map形式引入

    <select id="findAllStudentsByNameEmail" resultMap="StudentResult" parameterType="map">
    select stud_id, name,email, phone from Students
        where name=#{name} and email=#{email}
    </select>
  2. 使用參數替代

    <select id="findAllStudentsByNameEmail" resultMap="StudentResult">
    select stud_id, name,email, phone from Students
        where name=#{param1} and email=#{param2}
    </select>

緩存

默認狀況下,mybatis開啓一級緩存,對select進行緩存支持。 能夠經過<cache>開啓二級緩存
開啓耳機緩存的同時引起的問題:

  • 全部在映射語句文件定義的<select>語句的查詢結果都會被緩存

  • 全部的在映射語句文件定義的<insert>,<update> 和<delete>語句將會刷新緩存

  • 緩存根據最近最少被使用(Least Recently Used,LRU)算法管理

  • 緩存不會被任何形式的基於時間表的刷新(沒有刷新時間間隔),即不支持定時刷新機制

  • 緩存將存儲1024個 查詢方法返回的列表或者對象的引用

  • 緩存會被看成一個讀/寫緩存。這是指檢索出的對象不會被共享,而且能夠被調用者安全地修改,不會其餘潛 在的調用者或者線程的潛在修改干擾。(即,緩存是線程安全的)

<cache eviction="FIFO" flushInterval="60000" size="512"
readOnly="true"/>

說明:

  • eviction

    • LRU : 最近不多使用

    • FIFO : 先進先出

    • SOFT : 軟引用

    • WEAK : 若引用

  • flushInterval(定義刷新時間)

  • size 大小

  • readOnly 只讀

第四章 註解配置SQL映射器

  1. 基於註解的一些內容:

    • INSERT

    • UPDATE

    • SELECT

    • DELETE

  2. 基本使用

    @Insert("INSERT INTO STUDENTS(NAME,EMAIL,ADDR_ID, PHONE)
        VALUES(#{name},#{email},#{address.addrId},#{phone})")
      //經過如下註解實現主鍵 
      @Options(useGeneratedKeys = true, keyProperty = "studId")
    
    //經過此註解爲任意SQL語句指定主鍵值(使用此註解生成主鍵)
    @SelectKey(statement="SELECT STUD_ID_SEQ.NEXTVAL FROM DUAL",
    keyProperty="studId", resultType=int.class, before=true)
    
    //使用觸發器生成
    @SelectKey(statement="SELECT STUD_ID_SEQ.CURRVAL FROM DUAL",
    keyProperty="studId", resultType=int.class, before=false)
    
    
    //結果集映射  
    @Results(
    {
        @Result(id = true, column = "stud_id", property = "studId"),
        @Result(column = "name", property = "name"),
        @Result(column = "email", property = "email"),
        @Result(column = "addr_id", property = "address.addrId")
    })
    • 一對一映射

      • 嵌套sql語句形式

      //使用嵌套select 語句實現
      @Results(
      {
      @Result(id = true, column = "stud_id", property = "studId"),
      @Result(column = "name", property = "name"),
      @Result(column = "email", property = "email"),
      @Result(property = "address", column = "addr_id",
      one = @One(select = "com.mybatis3.mappers.StudentMapper.
      findAddressById"))
      })
      • 嵌套對象

        此種方式並無註解形式的實現 ,能夠經過在XML中定義映射`resultMap`集,而後經過`@ResultMap`進行映射
        @ResultMap("com.mybatis3.mappers.StudentMapper.
                       StudentWithAddressResult")
    • 一對多映射
      一樣的只有嵌套SQL的形式

      @Result(property = "courses", column = "tutor_id",
      many = @Many(select = "com.mybatis3.mappers.TutorMapper.
      findCoursesByTutorId"))
  3. 遇到的問題

    • 結果集不能重用,由於沒法賦予id, 因此沒法重用,哪怕相同都必須重寫寫
      能夠經過一個xml進行映射

      <mapper namespace="com.mybatis3.mappers.StudentMapper">
        <resultMap type="Student" id="StudentResult">
          <id property="studId" column="stud_id" />
          <result property="name" column="name" />
          <result property="email" column="email" />
          <result property="phone" column="phone" />
        </resultMap>
      </mapper>
      
          //經過此種方式解決沒法重用的問題
       @Select("SELECT * FROM STUDENTS WHERE STUD_ID=#{studId}")
            @ResultMap("com.mybatis3.mappers.StudentMapper.StudentResult")
    • 針對動態SQL經過工具類的方式生成SQL語句

      return new SQL()
      {
          {
              SELECT("tutor_id as tutorId, name, email");
              FROM("tutors");
               WHERE("tutor_id=" + tutorId);
            }
      } .toString();
      }
  4. 動態SQL映射

    • 建立動態SQL映射類

      public class TutorDynaSqlProvider
      {
          public String findTutorByIdSql(int tutorId)
          {
              return "SELECT TUTOR_ID AS tutorId, NAME, EMAIL FROM TUTORS
         WHERE TUTOR_ID=" + tutorId;
          } 
      }
      public String findTutorByNameAndEmailSql(Map<String, Object> map)
      {
          String name = (String) map.get("param1");
          String email = (String) map.get("param2");
          //you can also get those values using 0,1 keys
          //String name = (String) map.get("0");
          //String email = (String) map.get("1");
          return new SQL()
          {
              {
                  SELECT("tutor_id as tutorId, name, email");
                  FROM("tutors");
                  WHERE("name=#{name} AND email=#{email}");
              }
          } .toString();
      }
    • 添加動態SQL註解到方法上

      @SelectProvider(type=TutorDynaSqlProvider.class, method="findTutorByIdSql")
      Tutor findTutorById(int tutorId);

第五章 spring 集成

  1. 配置mybatis beans

    `applicationContext.xml` 中添加
<beans>
  <bean id="dataSource" class="org.springframework.jdbc.datasource. DriverManagerDataSource">
    <property name="driverClassName" value="com.mysql.jdbc.Driver" />
    <property name="url" value="jdbc:mysql://localhost:3306/elearning" />
    <property name="username" value="root" />
    <property name="password" value="admin" />
  </bean>
  <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="typeAliases" value="com.mybatis3.domain.Student, com.mybatis3.domain.Tutor" /> <property name="typeAliasesPackage" value="com.mybatis3.domain" />
<property name="typeHandlers" value="com.mybatis3.typehandlers.PhoneTypeHandler" />
<property name="typeHandlersPackage" value="com.mybatis3.typehandlers" />
<property name="mapperLocations" value="classpath*:com/mybatis3/**/*.xml" />
<property name="configLocation" value="WEB-INF/mybatisconfig.xml" />
  </bean>
</beans>

<bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
  <constructor-arg index="0" ref="sqlSessionFactory" />
</bean>

經過此種方式配置就能夠引用sqlSession

<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> 
    <property name="basePackage" value="com.mybatis3.mappers" />
</bean>

經過以上的方式掃描包中的映射器Mapper接口, 並自動註冊

mybatis關於mapper掃描有兩種方式 :

* 使用XML形式  
    ` <mybatis:scan base-package="com.mybatis3.mappers" />`
* 使用`@MapperScan`註解

很是感謝針對本書翻譯的工做者

相關文章
相關標籤/搜索