Mybatis的延遲加載
?一恰梢、什么是延遲加載
延遲加載: 就是在需要用到數(shù)據(jù)時(shí)才進(jìn)行加載佛南,不需要用到數(shù)據(jù)時(shí)就不加載數(shù)據(jù)。延遲加載也稱懶加載.好處: 先從單表查詢嵌言,需要時(shí)再?gòu)年P(guān)聯(lián)表去關(guān)聯(lián)查詢嗅回,大大提高數(shù)據(jù)庫(kù)性能,因?yàn)椴樵儐伪硪汝P(guān)聯(lián)查詢多張表速度要快摧茴。壞處: 因?yàn)橹挥挟?dāng)需要用到數(shù)據(jù)時(shí)绵载,才會(huì)進(jìn)行數(shù)據(jù)庫(kù)查詢,這樣在大批量數(shù)據(jù)查詢時(shí)蓬蝶,因?yàn)椴樵児ぷ饕惨臅r(shí)間尘分,所以可能造成用戶等待時(shí)間變長(zhǎng),造成用戶體驗(yàn)下降丸氛。
二培愁、實(shí)現(xiàn)需求
需求: 查詢賬戶(Account)信息并且關(guān)聯(lián)查詢用戶(User)信息。如果先查詢賬戶(Account)信息即可滿足要求缓窜,當(dāng)我們需要查詢用戶(User)信息時(shí)再查詢用戶(User)信息定续。把對(duì)用戶(User)信息的按需去查詢就是延遲加載『檀福 association私股、collection 具備延遲加載功能。
三恩掷、使用association實(shí)現(xiàn)延遲加載
需求:
查詢賬戶信息同時(shí)查詢用戶信息倡鲸。
3.1 賬戶的持久層dao接口
package com.llb.dao;import com.llb.domain.Account;import java.util.List;/** * Ceate By llb on 2019/8/7
*/publicinterface AccountMapper {
? ? /**? ? * 查詢賬戶所對(duì)應(yīng)的的用戶
? ? */? ? List findAccountAndUser();
}
3.2 賬戶的持久層映射文件
<?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.llb.dao.AccountMapper">
????<!--定義封裝account和user的resultMap-->
????<resultMap id="accountMap" type="com.llb.domain.Account">
????????<id property="id" column="id"></id>
????????<result property="uid" column="uid"></result>
????????<result property="money" column="money"></result>
????????<!--一對(duì)一的關(guān)系映射 JavaType:對(duì)應(yīng)的是哪個(gè)類 select 指定的內(nèi)容:查詢用戶的唯一標(biāo)識(shí) -->
????????<association property="user" column="uid" javaType="com.llb.domain.User" select="com.llb.dao.UserMapper.findById" ></association> ????</resultMap>
????<select id="findAccountAndUser" resultMap="accountMap"> select * from account </select>
</mapper>
3.3 用戶的持久層接口
package com.llb.dao;import com.llb.domain.User;import java.util.List;/** * 用戶的持久層接口
* Ceate By llb on 2019/8/5
*/publicinterface UserMapper {
? ? /**? ? * 根據(jù)id查詢所有用戶
? ? * @return*/? ? User findById(Integer id);
? ? /**? ? * 查詢出所有用戶,包含賬戶信息
? ? * @return*/? ? List findAccountAndUser();
}
3.4 用戶的持久層映射文件
<?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.llb.dao.UserMapper">? ?
????<!--配置 查詢結(jié)果的列名和實(shí)體類的屬性名的對(duì)應(yīng)關(guān)系-->? ?
????<resultMap id="userMap" type="com.llb.domain.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對(duì)象中accounts集合的映射? ? ? ofType:表示集合的類型-->? ? ? ?
????????<collection property="accounts" ofType="com.llb.domain.Account">? ? ? ? ? ?
????????????<id property="id" column="aid"></id>? ? ? ? ? ?
????????????<result property="uid" column="uid"></result>? ? ? ? ? ?
????????????<result property="money" column="money"></result>? ? ? ?
????????????</collection>? ?????????
????</resultMap>? ? <!--查詢出用戶所對(duì)應(yīng)的賬戶-->? ?
<select id="findAccountAndUser" resultMap="userMap">? ? ? ? select * from user left outer join account on user.id = account.uid? ? </select>? ? <!--根據(jù)id查詢用戶-->? ? <select id="findById" resultType="user" parameterType="int">? ? ? ? select * from user where id = #{id}? ? </select></mapper>
3.5 開啟mybatis的延遲加載策略
進(jìn)入 Mybaits 的官方文檔黄娘,找到 settings 的說(shuō)明信息:
我們需要在 Mybatis 的配置文件 SqlMapConfig.xml 文件中添加延遲加載的配置峭状。
? ? <!--配置參數(shù)克滴,延遲加載-->
? ? <settings>
? ? ? ? <!--開啟mybatis支持延遲加載-->
? ? ? ? <setting name="lazyLoadingEnabled" value="true"/>
? ? ? ? <!--不配置也可以:默認(rèn)為false;允許觸發(fā)方法進(jìn)行延遲加載,否則立即加載-->
? ? ? ? <setting name="aggressiveLazyLoading" value="false"></setting>
? ? </settings>
3.6 編寫測(cè)試只查賬戶信息不查用戶信息
*/publicclass AccountTest {
? ? InputStream in =null;
? ? AccountMapper mapper =null;
? ? SqlSession sqlSession =null;
? ? /**? ? * 在測(cè)試方法執(zhí)行前執(zhí)行
? ? * @throws IOException
? ? */? ? @Before
? ? publicvoidinit()throws IOException {
? ? ? ? //1.讀取配置文件优床,生成字節(jié)流in = Resources.getResourceAsStream("SqlMapConfig.xml");
? ? ? ? //2.獲取sqlSessionFactory對(duì)象SqlSessionFactory factory =new SqlSessionFactoryBuilder().build(in);
? ? ? ? //3.獲取sqlSession對(duì)象sqlSession = factory.openSession();
? ? ? ? //4.獲取dao的代理對(duì)象mapper = sqlSession.getMapper(AccountMapper.class);
? ? }
? ? /**? ? * 測(cè)試方法執(zhí)行后執(zhí)行
? ? * @throws IOException
? ? */? ? @After
? ? publicvoiddestory()throws IOException {
? ? ? ? sqlSession.commit();
? ? ? ? //6.釋放資源? ? ? ? sqlSession.close();
? ? ? ? in.close();
? ? }
? ? /**? ? * 查詢出賬戶所對(duì)應(yīng)的user
? ? */? ? @Test
? ? publicvoid testFindAccountAndUser(){
? ? ? ? List accountUser = mapper.findAccountAndUser();//? ? ? ? for (Account account: accountUser) {//? ? ? ? ? ? System.out.println(account);//? ? ? ? }? ? }
}
3.7 測(cè)試結(jié)果
當(dāng)不進(jìn)行配置時(shí)劝赔,立即加載,查詢account所對(duì)應(yīng)的user胆敞,一起將user查詢出來(lái):
配置后着帽,對(duì)account進(jìn)行查詢放入到list集合中,并沒(méi)有涉及到user對(duì)象移层,所以就沒(méi)有發(fā)出 SQL 語(yǔ)句查詢賬戶所關(guān)聯(lián)的 User 對(duì)象的查詢仍翰。:
四、使用collection實(shí)現(xiàn)緩存策略
同樣我們也可以在一對(duì)多關(guān)系配置的<collection>結(jié)點(diǎn)中配置延遲加載策略幽钢。
<collection>結(jié)點(diǎn)中也有 select 屬性歉备,column 屬性。
需求:
????完成加載用戶對(duì)象時(shí)匪燕,查詢?cè)撚脩羲鶕碛械馁~戶信息蕾羊。
4.1 在User實(shí)體類中加入List<Account>屬性
package com.llb.domain;import java.io.Serializable;
import java.util.Date;import java.util.List;/** * Ceate By llb on 2019/8/5
*/publicclassUserimplements Serializable{
? ? private Integer id;
? ? private String username;
? ? private String address;
? ? private String sex;
? ? private Date birthday;
? ? //一對(duì)多關(guān)系。一的方包含多的一方所有對(duì)象privateList accounts;
? ? @Override
? ? public String toString() {
? ? ? ? return"User{" +? ? ? ? ? ? ? ? "id=" + id +? ? ? ? ? ? ? ? ", username='" + username + '\'' +? ? ? ? ? ? ? ? ", address='" + address + '\'' +? ? ? ? ? ? ? ? ", sex='" + sex + '\'' +? ? ? ? ? ? ? ? ", birthday=" + birthday +? ? ? ? ? ? ? ? ", accounts=" + accounts +? ? ? ? ? ? ? ? '}';
? ? }
? ? publicList getAccounts() {
? ? ? ? return accounts;
? ? }
? ? publicvoidsetAccounts(List accounts) {
? ? ? ? this.accounts = accounts;
? ? }
? ? public Integer getId() {
? ? ? ? return id;
? ? }
? ? publicvoid setId(Integer id) {
? ? ? ? this.id = id;
? ? }
? ? public String getUsername() {
? ? ? ? return username;
? ? }
? ? publicvoid setUsername(String username) {
? ? ? ? this.username = username;
? ? }
? ? public String getAddress() {
? ? ? ? return address;
? ? }
? ? publicvoid setAddress(String address) {
? ? ? ? this.address = address;
? ? }
? ? public String getSex() {
? ? ? ? return sex;
? ? }
? ? publicvoid setSex(String sex) {
? ? ? ? this.sex = sex;
? ? }
? ? public Date getBirthday() {
? ? ? ? return birthday;
? ? }
? ? publicvoid setBirthday(Date birthday) {
? ? ? ? this.birthday = birthday;
? ? }
}
4.2 編寫用戶接口和配置文件
UserMapper.class:
package com.llb.dao;import com.llb.domain.User;import java.util.List;/** * 用戶的持久層接口
* Ceate By llb on 2019/8/5
*/publicinterface UserMapper {
? ? /**? ? * 根據(jù)id查詢所有用戶
? ? * @return*/? ? User findById(Integer id);
? ? /**? ? * 查詢出所有用戶帽驯,包含賬戶信息
? ? * @return*/? ? List findAccountAndUser();
}
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.llb.dao.UserMapper">
<!--配置 查詢結(jié)果的列名和實(shí)體類的屬性名的對(duì)應(yīng)關(guān)系-->
<resultMap id="userMap" type="com.llb.domain.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對(duì)象中accounts集合的映射 ofType:表示集合的類型-->
????<collection property="accounts" ofType="com.llb.domain.Account" select="com.llb.dao.AccountMapper.findAccountById" column="id"> </collection>
</resultMap> <!--查詢出用戶所對(duì)應(yīng)的賬戶-->
????<select id="findAccountAndUser" resultMap="userMap">
????????select * from user
????</select>
????<!--根據(jù)id查詢用戶-->
????<select id="findById" resultType="user" parameterType="int">
????????select * from user where id = #{id}
????</select>
</mapper>
4.3 使用測(cè)試方法進(jìn)行測(cè)試
publicclass UserTest {
? ? InputStream in =null;
? ? UserMapper mapper =null;
? ? SqlSession sqlSession =null;
? ? /**? ? * 在測(cè)試方法執(zhí)行前執(zhí)行
? ? * @throws IOException
? ? */? ? @Before
? ? publicvoidinit()throws IOException {
? ? ? ? //1.讀取配置文件龟再,生成字節(jié)流in = Resources.getResourceAsStream("SqlMapConfig.xml");
? ? ? ? //2.獲取sqlSessionFactory對(duì)象SqlSessionFactory factory =new SqlSessionFactoryBuilder().build(in);
? ? ? ? //3.獲取sqlSession對(duì)象sqlSession = factory.openSession();
? ? ? ? //4.獲取dao的代理對(duì)象mapper = sqlSession.getMapper(UserMapper.class);
? ? }
? ? /**? ? * 測(cè)試方法執(zhí)行后執(zhí)行
? ? * @throws IOException
? ? */? ? @After
? ? publicvoiddestory()throws IOException {
? ? ? ? sqlSession.commit();
? ? ? ? //6.釋放資源? ? ? ? sqlSession.close();
? ? ? ? in.close();
? ? }
? ? /**? ? * 查詢出所有用戶所對(duì)應(yīng)的賬戶
? ? */? ? @Test
? ? publicvoid findUserAndAccount(){
? ? ? ? List users = mapper.findAccountAndUser();
? ? ? ? }
}
測(cè)試結(jié)果:
我們沒(méi)有使用Accout,也只對(duì)User進(jìn)行了查詢尼变。
Mybatis緩存
源碼:https://github.com/PopsiCola/SSM-mybatis/tree/association_lazy
歡迎star