mybatis延遲加載、立即加載、一級緩存、二級緩存

1、Mybatis中的延遲加載
問題:在一對多中,當我們有一個用戶,它有100個賬戶。
在查詢用戶的時候,要不要把關聯的賬戶查出來?
在查詢賬戶的時候,要不要把關聯的用戶查出來?

在查詢用戶時,用戶下的賬戶信息應該是,什麼時候使用,什麼時候查詢的。
在查詢賬戶時,賬戶的所屬用戶信息應該是隨着賬戶查詢時一起查詢出來。

什麼是延遲加載
在真正使用數據時才發起查詢,不用的時候不查詢。按需加載(懶加載)
什麼是立即加載
不管用不用,只要一調用方法,馬上發起查詢。

在對應的四種表關係中:一對多,多對一,一對一,多對多
一對多,多對多:通常情況下我們都是採用延遲加載。
多對一,一對一:通常情況下我們都是採用立即加載。

1.延遲加載(一對一,一對多)

@Test
    public void testFindAll(){
        List<Account> accounts = accountDao.findAll();
        for(Account account : accounts){
            System.out.println("--------每個account的信息------------");
            System.out.println(account);
            /**
             * 執行account.getUser時,才加載用戶信息
             */
            System.out.println(account.getUser());
        }
    }

@Test
public void testFindAll(){
List<User> users = userDao.findAll();
for(User user : users){
System.out.println("-----每個用戶的信息------");
System.out.println(user);
System.out.println(user.getAccounts());
}
}
 
public class Account implements Serializable {

    private Integer id;
    private Integer uid;
    private Double money;

    //從表實體應該包含一個主表實體的對象引用
    private User user;
}


public class User implements Serializable {

private Integer id;
private String username;
private String address;
private String sex;
private Date birthday;

//一對多關係映射:主表實體應該包含從表實體的集合引用
private List<Account> accounts;
}
public interface IAccountDao {

    /**
     * 查詢所有賬戶,同時還要獲取到當前賬戶的所屬用戶信息
     * @return
     */
    List<Account> findAll();

    /**
     * 根據用戶id查詢賬戶信息
     * @param uid
     * @return
     */
    List<Account> findAccountByUid(Integer uid);

}

public interface IUserDao {

/**
* 查詢所有用戶,同時還要獲取到當前賬戶的所屬用戶信息
* @return
*/
List<User> findAll();

/**
* 根據用戶id查詢賬戶信息
* @param uid
* @return
*/
List<User> findById(Integer uid);

}
 
<?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="jdbcConfig.properties"></properties>

    <!--配置參數-->
    <settings>
        <!--開啓Mybatis支持延遲加載-->
        <setting name="lazyLoadingEnabled" value="true"/>
        <setting name="aggressiveLazyLoading" value="false"></setting>
    </settings>

    <!--使用typeAliases配置別名,它只能配置domain中類的別名 -->
    <typeAliases>
        <package name="com.itheima.domain"></package>
    </typeAliases>

    <!--配置環境-->
    <environments default="mysql">
        <!-- 配置mysql的環境-->
        <environment id="mysql">
            <!-- 配置事務 -->
            <transactionManager type="JDBC"></transactionManager>

            <!--配置連接池-->
            <dataSource type="POOLED">
                <property name="driver" value="${jdbc.driver}"></property>
                <property name="url" value="${jdbc.url}"></property>
                <property name="username" value="${jdbc.username}"></property>
                <property name="password" value="${jdbc.password}"></property>
            </dataSource>
        </environment>
    </environments>
    <!-- 配置映射文件的位置 -->
    <mappers>
        <package name="com.itheima.dao"></package>
    </mappers>
</configuration>

Account.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.itheima.dao.IAccountDao">

    <!-- 定義封裝account和user的resultMap -->
    <resultMap id="accountUserMap" type="account">
        <id property="id" column="id"></id>
        <result property="uid" column="uid"></result>
        <result property="money" column="money"></result>
        <!-- 一對一的關係映射:配置封裝user的內容
        select屬性指定的內容:查詢用戶的唯一標識:
        column屬性指定的內容:用戶根據id查詢時,所需要的參數的值
        -->
        <association property="user" column="uid" javaType="user" select="com.itheima.dao.IUserDao.findById"></association>
    </resultMap>

    <!-- 查詢所有 -->
    <select id="findAll" resultMap="accountUserMap">
        select * from account
    </select>

    <!-- 根據用戶id查詢賬戶列表 -->
    <select id="findAccountByUid" resultType="account">
        select * from account where uid = #{uid}
    </select>

</mapper>

User.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.itheima.dao.IUserDao">

    <!-- 定義User的resultMap-->
    <resultMap id="userAccountMap" type="user">
        <id property="id" column="id"></id>
        <result property="username" column="username"></result>
        <result property="address" column="address"></result>
        <result property="sex" column="sex"></result>
        <result property="birthday" column="birthday"></result>
        <!-- 配置user對象中accounts集合的映射 -->
        <collection property="accounts" ofType="account" select="com.itheima.dao.IAccountDao.findAccountByUid" column="id"></collection>
    </resultMap>

    <!-- 查詢所有 -->
    <select id="findAll" resultMap="userAccountMap">
        select * from user
    </select>

    <!-- 根據id查詢用戶 -->
    <select id="findById" parameterType="INT" resultType="user">
        select * from user where id = #{uid}
    </select>

</mapper>

 


 

2、Mybatis中的緩存
什麼是緩存
存在於內存中的臨時數據。
爲什麼使用緩存
減少和數據庫的交互次數,提高執行效率。
什麼樣的數據能使用緩存,什麼樣的數據不能使用
適用於緩存:
經常查詢並且不經常改變的。
數據的正確與否對最終結果影響不大的。
不適用於緩存:
經常改變的數據
數據的正確與否對最終結果影響很大的。
例如:商品的庫存,銀行的匯率,股市的牌價。
Mybatis中的一級緩存和二級緩存
一級緩存:
它指的是Mybatis中SqlSession對象的緩存。
當我們執行查詢之後,查詢的結果會同時存入到SqlSession爲我們提供一塊區域中。
該區域的結構是一個Map。當我們再次查詢同樣的數據,mybatis會先去sqlsession中
查詢是否有,有的話直接拿出來用。
當SqlSession對象消失時,mybatis的一級緩存也就消失了。

二級緩存:
它指的是Mybatis中SqlSessionFactory對象的緩存。由同一個SqlSessionFactory對象創建的SqlSession共享其緩存。
二級緩存的使用步驟:
第一步:讓Mybatis框架支持二級緩存(在SqlMapConfig.xml中配置)
第二步:讓當前的映射文件支持二級緩存(在IUserDao.xml中配置)
第三步:讓當前的操作支持二級緩存(在select標籤中配置)

 

1.一級緩存

  /**
     * 測試一級緩存
     */
    @Test
    public void testFirstLevelCache(){
        User user1 = userDao.findById(41);
        System.out.println(user1);

      // sqlSession.close();
     // 再次獲取SqlSession對象
     //  sqlSession = factory.openSession();

     // sqlSession.clearCache();//此方法也可以清空緩存

   userDao = sqlSession.getMapper(IUserDao.class);

        User user2 = userDao.findById(41);
        System.out.println(user2);

        System.out.println(user1 == user2);
    }

    /**
     * 測試緩存的同步
     */
    @Test
    public void testClearlCache(){
        //1.根據id查詢用戶
        User user1 = userDao.findById(41);
        System.out.println(user1);

        //2.更新用戶信息
        user1.setUsername("update user clear cache");
        user1.setAddress("北京市海淀區");
        userDao.updateUser(user1);

        //3.再次查詢id爲41的用戶
        User user2 = userDao.findById(41);
        System.out.println(user2);

        System.out.println(user1 == user2);
    }
}

 

二級緩存

@Test
    public void testFirstLevelCache(){
        SqlSession sqlSession1 = factory.openSession();
        IUserDao dao1 = sqlSession1.getMapper(IUserDao.class);
        User user1 = dao1.findById(41);
        System.out.println(user1);
        sqlSession1.close();//一級緩存消失

        SqlSession sqlSession2 = factory.openSession();
        IUserDao dao2 = sqlSession2.getMapper(IUserDao.class);
        User user2 = dao2.findById(41);
        System.out.println(user2);
        sqlSession2.close();

        System.out.println(user1 == user2);
    }
<?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="jdbcConfig.properties"></properties>

    <settings>
        <setting name="cacheEnabled" value="true"/>
    </settings>
    
    <!--使用typeAliases配置別名,它只能配置domain中類的別名 -->
    <typeAliases>
        <package name="com.itheima.domain"></package>
    </typeAliases>

    <!--配置環境-->
    <environments default="mysql">
        <!-- 配置mysql的環境-->
        <environment id="mysql">
            <!-- 配置事務 -->
            <transactionManager type="JDBC"></transactionManager>

            <!--配置連接池-->
            <dataSource type="POOLED">
                <property name="driver" value="${jdbc.driver}"></property>
                <property name="url" value="${jdbc.url}"></property>
                <property name="username" value="${jdbc.username}"></property>
                <property name="password" value="${jdbc.password}"></property>
            </dataSource>
        </environment>
    </environments>
    <!-- 配置映射文件的位置 -->
    <mappers>
        <package name="com.itheima.dao"></package>
    </mappers>
</configuration>
<?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.itheima.dao.IUserDao">
    <!--開啓user支持二級緩存-->
    <cache/>

    <!-- 查詢所有 -->
    <select id="findAll" resultType="user">
        select * from user
    </select>

    <!-- 根據id查詢用戶 -->
    <select id="findById" parameterType="INT" resultType="user" useCache="true">
        select * from user where id = #{uid}
    </select>

    <!-- 更新用戶信息-->
    <update id="updateUser" parameterType="user">
        update user set username=#{username},address=#{address} where id=#{id}
    </update>
</mapper>

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章