1. 程式人生 > >延遲載入、快取、spring與宣告式事務

延遲載入、快取、spring與宣告式事務

什麼是延遲載入

  • 延遲載入又稱(懶載入)
  • resultMap中的 associationcollection 標籤就具有延遲載入的功能(一對一,一對多的關係自帶延遲載入,在開發裡面最常用的)
    - 作用是:什麼時候用什麼時候載入

設定延遲載入

		<!--開啟延遲載入-->
		<setting name="lazyLoadingEnabled" value="true"/>
		<!--關閉積極載入-->
		<setting name="aggressiveLazyLoading" value="false"
/> <setting name="lazyLoadTriggerMethods" value=""/>(呼叫toString無效時載入)
  • 查詢主表的資訊(根據id來進行查詢,子查詢在resultMap(select="")如果是另一個包引入進來要加上完整的包名和類名,關聯的欄位)
    呼叫其方法時,會走子查詢;

沒有載入延遲的時候控制檯顯示

  • 會輸出兩句 查詢
    在這裡插入圖片描述

載入延遲的時候控制檯顯示

  • 獲取誰,就輸出誰的查詢
    在這裡插入圖片描述

快取

  • 好處:提高載入的速度,同樣的資料,不用一直查詢資料庫
  • 缺點;可能查詢出髒資料;

一級快取:(一級快取的作用域是針對於我們的sqlsession(出了sqlsession 就沒有一級快取);預設一級快取自動開啟;

  • 如果是要關閉一級快取,需要呼叫其commit()方法;
public class Test {
    public static void main(String[] args) {
        String path = "mybatis-config.xml";
        try {
        InputStream is = Resources.getResourceAsStream(path);
        SqlSessionFactory sqlSessionFactory =
new SqlSessionFactoryBuilder().build(is); //得到sqlSession SqlSession sqlSession = sqlSessionFactory.openSession(); RoleMapper roleMapper = sqlSession.getMapper(RoleMapper.class); Role role = roleMapper.selectByIdRole(2); System.out.println(role.getRoleName()); //sqlSession.commit(); 未呼叫commit() System.out.println("-------分割線--------"); RoleMapper roleMapper1= sqlSession.getMapper(RoleMapper.class); Role role1= roleMapper1.selectByIdRole(2); System.out.println(role1.getRoleName());
未呼叫 commit()釋出方法程式碼顯示

第二個經理就是在快取中獲取
在這裡插入圖片描述

呼叫 commit()釋出方法程式碼顯示

在這裡插入圖片描述

二級快取:(是針對於整個mapper(namespace=“com.offcn.dao.UserMapper”))只要在同一個mapper中,快取都有效果;

  • 配置二級快取要注意(settings 裡面配置兩句話(開啟快取配置的按鈕,第二個是要把你的物件序列化,
  • 第三個就是要把你的namespace 配置
    標籤,這樣就配置了二級快取(用二級快取的時候,一定要sqlsession.commit()(關閉一級快取,載入二級快取)),
  • 步驟:在nameSpace 加上 cache;重新整理二級快取的方法:sqlSession.clearCache();禁用:
需要新增 cache
<mapper namespace="com.offcn.dao.RoleMapper">
    <cache />
    <select id="selectByIdRole" parameterType="int" resultType="Role">
        select * from smbms_role where id=#{id}
    </select>
</mapper>

在這裡插入圖片描述

自定義快取

  • 第一步 匯入jar包
    • 匯入一個mybatis-spring-1.2.0.jar
  • 第二步 所有的都是由spring來進行管理 ,寫spring 的核心配置檔案
    • applicationContext.xml(第一個bean 獲取連線資料來源,
    • 第二個bean 獲取獲取sqlSessionFactroy(引入資料庫資源(dataSource) 第二個引入myBatis 核心配置檔案)
    • 第三個bean (配置dao層 第一個是通過這個物件.MapperFactoryBean(引入你的介面的類,第二個是你的sqlSessionFactroy)"(第二種方式是MapperScannerConfigurer )))

spring 與 宣告式事務()

  • 第一步: 引入資料庫的配置資訊(dataSource)
  • 第二步 :配置dao 層 配置服務層
  • 第三步: 配置事物管理器DataSourceTransactionManager (引入資料來源資源,也就是dataSource)
  • 第四步 :定義事務通知(一種不用註解)(用註解)
    • ( 代表對應的方法名 第二個代表是事物的傳播行為,事物失效的時間,事物的隔離級別–> <!– 指定異常進行回滾 這個代表引數的意思 )
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
        destroy-method="close">
        <property name="driverClassName" value="com.mysql.jdbc.Driver" />
        <!-- <property name="url">
            <value><![CDATA[jdbc:mysql://127.0.0.1:3306/smbms?
                    useUnicode=true&characterEncoding=utf-8]]></value>
        </property> -->
        <property name="url" value="jdbc:mysql://127.0.0.1:3306/smbms?
                        useUnicode=true&amp;characterEncoding=utf-8" />
        <property name="username" value="root" />
        <property name="password" value="root" />
    </bean>
     <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
         <!--引入資料庫資源-->
         <property name="dataSource" ref="dataSource"></property>
         <!--載入mybatis核心配置檔案-->
         <property name="configLocation" value="classpath:mybatis-config.xml"></property>
     </bean>

    <!--配置userDao-->
     <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
         <property name="basePackage" value="com.offcn.mapper"></property>
     </bean>
<!--定義一個事物管理器-->
     <bean id="transactionManger" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
         <!--引入資料來源-->
         <property name="dataSource" ref="dataSource"></property>
     </bean>

    <!--定義事物通知-->
    <tx:advice id="txAdvice" transaction-manager="transactionManger">
        <tx:attributes>
            <!--name代表對應的方法名 第二個代表是事物的傳播行為,事物失效的時間,事物的隔離級別--> <!--指定異常進行回滾-->
            <tx:method name="find" propagation="SUPPORTS" timeout="-1" isolation="DEFAULT" />
            <tx:method name="add" propagation="REQUIRED"></tx:method>
            <tx:method name="*" propagation="REQUIRED"></tx:method>
        </tx:attributes>
    </tx:advice>

    <!--定義切面-->
    <aop:config>
        <aop:pointcut id="serviceMethod" expression="execution(* com.offcn.service.UserService.*(..))"></aop:pointcut>
        <aop:advisor advice-ref="txAdvice" pointcut-ref="serviceMethod"></aop:advisor>
    </aop:config>

public class UserServiceImpl implements UserService {
    private UserMapper userMapper;

    public void setUserMapper(UserMapper userMapper) {
        this.userMapper = userMapper;
    }

    @Override
    public void addUser(List<User> userList) {
        for (User user: userList) {
            userMapper.addUser(user);
        }
    }
}

第二種方式用的關鍵的註解 ()

   <!--自動掃描包-->
   <context:component-scan base-package="com.offcn.service"/>
   <!--開啟註解驅動-->
   <tx:annotation-driven/>
  • 在 類前面 也就是你的service 的類上 @Transactional
  • 再到你的方法上配置具體的 @Transactional(propagation = Propagation.REQUIRED) 等同於 <tx:method name="*" propagation=“REQUIRED” />
  • 前面學過的註解 dao層的註解 @Repository service 層的@service @Autowired 按照型別
@Service("userSerbice")
/*事務的註解*/
@Transactional
public class UserServiceImpl implements UserService {
    @Resource
    private UserMapper userMapper;

    public void setUserMapper(UserMapper userMapper) {
        this.userMapper = userMapper;
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED)
    /*REQUIRED預設的,除了查詢都用這個*/
    public void addUser(List<User> userList) {
        for (User user: userList) {
            userMapper.addUser(user);
        }
    }
}