mybatis 延遲加載

mybatis 延遲加載

什麼是延遲加載

延遲加載又叫懶加載,也叫按需加載,也就是說先加載主信息,須要的時候,再去加載從信息。代碼中有查詢語句,當執行到查詢語句時,並非立刻去DB中查詢,而是根據設置的延遲策略將查詢向後推遲。java

何時會執行延遲加載

配置以後在對關聯對象進行查詢時使用延遲加載。sql

延遲加載策略
直接加載

遇到代碼中查詢語句,立刻到DB中執行select語句進行查詢。(這種只能用於多表單獨查詢)服務器

侵入式延遲加載

將關聯對象的詳情(具體數據,如id、name)侵入到主加載對象,做爲主加載對象的詳情的一部分出現。當要訪問主加載對象的詳情時纔會查詢主表,但因爲關聯對象詳情做爲主加載對象的詳情一部分出現,因此這個查詢不只會查詢主表,還會查詢關聯表。mybatis

深度延遲加載

將關聯對象的詳情(具體數據,如id、name)侵入到主加載對象,做爲主加載對象的詳情的一部分出現。當要訪問主加載對象的詳情時纔會查詢主表,但因爲關聯對象詳情做爲主加載對象的詳情一部分出現,因此這個查詢不只會查詢主表,還會查詢關聯表。app

使用延遲加載的目的

減輕DB服務器的壓力,由於咱們延遲加載只有在用到須要的數據纔會執行查詢操做。框架

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

咱們用關聯查詢來實現延遲加載,假設咱們如今要查出用戶和用戶角色。測試

首先咱們在user中添加查詢userVo的方法和xml。fetch

<!--userMapper.xml-->

....
<resultMap id="BaseResultMap" type="com.redstar.basemapper.pojo.User">
        <id column="id" jdbcType="VARCHAR" property="id"/>
        <result column="name" jdbcType="VARCHAR" property="name"/>
        <result column="age" jdbcType="INTEGER" property="age"/>
        <result column="role_id" jdbcType="INTEGER" property="roleId"/>
    </resultMap>
    <resultMap id="userRoleMapSelect" type="com.redstar.basemapper.pojo.UserVo">
        <association property="user" resultMap="BaseResultMap"/>
        <association property="role" fetchType="lazy" column="{id=role_id}"
                     select="com.redstar.basemapper.dao.RoleMapper.getRoleById"/>
    </resultMap>
    <sql id="Base_Column_List">
    id, `name`, age, role_id
  </sql>
    <select id="getUserVo" resultMap="userRoleMapSelect">
      select * from user where id=#{userId}
    </select>
...
    
    
    
    <!--roleMapper.xml-->
...    
    <resultMap id="BaseResultMap" type="com.redstar.basemapper.pojo.Role">
    <id column="id" jdbcType="INTEGER" property="id" />
    <result column="role_name" jdbcType="VARCHAR" property="roleName" />
  </resultMap>
  <sql id="Base_Column_List">
    id, role_name
  </sql>
  <select id="getRoleById" resultMap="BaseResultMap">
    select * from role where id=#{id}
  </select>
...

測試用例代理

@RunWith(SpringRunner.class)
@SpringBootTest
public class BaseMapperApplicationTests {
    @Autowired
    private UserMapper userMapper;

    @Autowired
    private RoleMapper roleMapper;

    @Test
    public void getUserVo() {
        System.out.println(userMapper.getUserVo("12312232"));
//        System.out.println(userMapper.getUserById("12312232"));
//        System.out.println(roleMapper.getRoleById(1));

    }


}

輸出結果:code

UserVo{user=User [Hash = 1937575946, id=12312232, name=哇哈哈啊娃哈哈哇哈哈哈哈哈哈哈, age=48, roleId=1, serialVersionUID=1], role=Role [Hash = 317053574, id=1, roleName=admin, serialVersionUID=1]}
注意
許多對延遲加載原理不太熟悉的朋友會常常遇到一些莫名其妙的問題:有些時候延遲加載 能夠獲得數據,有些時候延遲加載就會報錯,爲何會出現這種狀況呢? MyBatis 延遲加載是經過動態代理實現的,當調用配直爲延遲加載的屬性方法時, 動態代 理的操做會被觸發,這些額外的操做就是經過 MyBatis 的 SqlSessio口去執行嵌套 SQL 的 。 因爲在和某些框架集成時, SqlSession 的生命週期交給了框架來管理,所以當對象超出 SqlSession 生命週期調用時,會因爲連接關閉等問題而拋出異常 。 在和 Spring 集成時,要 確保只能在 Service 層調用延遲加載的屬性 。 當結果從 Service 層返回至 Controller 層時, 若是 獲取延遲加載的屬性值,會由於 SqlSessio口已經關閉而拋出異常 。
相關文章
相關標籤/搜索