1. 程式人生 > >MyBatis加強學習筆記

MyBatis加強學習筆記

高階對映

通過定義resultMap來實現結果集自動封裝到指定物件並返回結果的一種對映方式

resultMap:

  • 屬性:
    • type:型別名稱
    • id:resultMap的唯一標識
  • 節點:
    • id:主鍵列,可設可不設 但可能影響查詢效率
      • column:sql結果集中返回的列名
      • property:將要對映到的類中的屬性名稱
    • result:普通列,
      • 屬性與主鍵列相同
    • association:用於一對一關係對映,
      • id,屬性與主鍵列相同
      • result,屬性與主鍵列相同
      • select
      • property
      • column
    • collection:用於一對多關係對映,
      • id,屬性與主鍵列相同
      • result,屬性與主鍵列相同
      • ofType:對應的目標型別(不能使用javaType,否則無法以List的形式呼叫setter方法)

延遲載入

也稱為懶載入,在查詢時先載入主資訊,在需要時才查詢從資訊。實現懶載入有以下三點需要注意:

  1. 在MyBatis中,resultMap標籤的association標籤和collection標籤具有延遲載入的功能。
  2. 在SqlMapConfig.xml中配置setting標籤
  3. 使用巢狀的select語句不當時會造成N+1問題----每個查詢跟著一個查詢,即一條資料要連續訪問兩次資料庫。因此不建議使用巢狀的select語句
<settings>
    <!-- 開啟延遲載入,預設值為true -->
    <setting name="lazyLoadingEnabled" value="true"></setting>
    <!-- 設定積極懶載入,預設為true,設定為false之後則不會立即載入從資料 -->
    <setting name="aggressiveLazyLoading" value="false"></setting>
</settings>

mapper檔案使用巢狀查詢

//省略外層的resultMap標籤
<association property="user" select="com.mapper.UserMapper.findUserById" column="user_id"><association>

association

  • select屬性:指定關聯查詢的查詢語句(前提是需要存在這條對應的statement),然後將查詢結果封裝到property屬性指定的變數中
  • column屬性:傳入statement的變數值,如果只有一個引數則直接傳指定列所查詢出的結果;如果有多個引數需按{col1=prop1,col2=prop2}的形式傳入。 SqlMapConfig.xml對應的setting:

collection

查詢快取

一級快取:

  • 存在於SqlSession中,在SqlSession中有一個數據區域,是Map結構,這個區域就是一級快取,以及快取中key為sql語句、條件、statement等資訊組成的唯一值,value為查詢出的結果物件
  • 預設查詢開啟,修改關閉
  • 當執行了修改資料操作(commit)時會清空快取

二級快取:

  • 存在於namespace下的mapper中,在namespace中有一個數據區域,也是Map結構
  • 預設關閉,需要手動開啟
  • 需要開啟總開關(在SqlMapConfig.xml中),且在mapper檔案中也需啟用配置

總結:

  • 對於訪問響應速度要求極高的,但是實時性不高的查詢可以使用二級快取技術,注意在使用二級快取的時候要設定一下自動重新整理的間隔(cache標籤中有一個flashInterval屬性)來定時重新整理二級快取,這個重新整理間隔根據具體需求來設定,比如設定30分鐘、60分鐘等,單位為毫秒)
  • 二級快取對細粒度的資料,快取實現較差。當訪問量較大 又需要每次查詢都是最新資料時無法實現只重新整理指定記錄的資訊而不重新整理其他記錄的資訊,因為二級快取是mapper級別的,當想要重新整理一條記錄的快取時,所有記錄的快取都將被清空

Spring和MyBatis整合

整合思路:

  1. 資料來源交由Spring管理
  2. SqlSessionFactory交由Spring進行單例管理
  3. 由Spring管理原始Dao的實現類或者mapper代理類

整合步驟:

  1. 導包
  2. Mybatis的SqlMapConfig配置檔案不需要再配置資料來源,只需要載入mapper配置檔案即可(如無需進行其他設定項)
  3. 完成mapper類編寫,完成mapper配置檔案,完成資料庫配置檔案
  4. 在Spring配置檔案中配置資料來源,載入SqlMapConfig配置檔案,載入mapper類
  5. 完成測試類編寫

程式碼實現:

  • MyBatis配置檔案SqlMapConfig.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>
	<mappers>
		<mapper resource="com/ms/mapper/UserMapper.xml" />
	</mappers>
</configuration>
  • Mapper配置檔案UserMapper.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.ms.mapper.UserMapper">
	<select id="findUserById" parameterType="int" resultType="com.ms.domain.User">
		SELECT * FROM user WHERE id=#{id}
	</select>
</mapper>
  • Spring配置檔案application.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
	xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
	xsi:schemaLocation="http://www.springframework.org/schema/beans 
       					   http://www.springframework.org/schema/beans/spring-beans.xsd
       					   http://www.springframework.org/schema/aop
       					   http://www.springframework.org/schema/aop/spring-aop.xsd
       					   http://www.springframework.org/schema/context 
       					   http://www.springframework.org/schema/context/spring-context.xsd
       					   http://www.springframework.org/schema/tx
       					   http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
	<context:property-placeholder location="db.properties"/>
	
	<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
		<property name="driverClassName" value="${db.driver}" />
		<property name="url" value="${db.url}" />
		<property name="username" value="${db.username}" />
		<property name="password" value="${db.password}" />
		<property name="maxActive" value="10" />
		<property name="maxIdle" value="5" />
	</bean>
	
	<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
		<property name="configLocation" value="mybatis/SqlMapConfig.xml" />
		<property name="dataSource" ref="dataSource" />
	</bean>
	<!-- 單個mapper配置 -->
	<bean id="userMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">
		<property name="mapperInterface" value="com.ms.mapper.UserMapper" />
		<property name="sqlSessionFactory" ref="sqlSessionFactory" />
	</bean>
	<!-- 批量一個包配置  -->
	<!-- <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
		<property name="basePackage" value="com.ms.mapper" />
		已經預設配置了sqlSessionFactory 但只有一個sqlSessionFactory時
	</bean> -->
</beans>
  • UserMapper.java
package com.ms.mapper;
import com.ms.domain.User;

public interface UserMapper {

    public User findUserById(int id);

}
  • 測試程式碼
package com.ms.test;

import org.junit.Before;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.ms.domain.User;

import com.ms.mapper.UserMapper;

public class TestUserMapper {

    ApplicationContext applicationContext;

    @Before
    public void setUp() {
        applicationContext = new ClassPathXmlApplicationContext("spring/applicationContext.xml");
    }

    @Test
    public void findUserById() {
        UserMapper userMapper = (UserMapper) applicationContext.getBean("userMapper");
        User user = userMapper.findUserById(1);
        System.out.println(user);
    }

}