Mybatis加载策略及注解开发

MyBatis加载策略

延迟加载

  • 在需要用到数据时才进行加载,不需要用到数据时就不加载数据。延迟加载也称懒加载。

当有一个用户,它有个100个订单
在查询用户时,用户下的订单应该是,什么时候用,什么时候查询。
在查询订单时,订单所属的用户信息应该是随着订单一起查询出来。

  • 优点:先从单表查询,需要时再从关联表去关联查询,大大提高数据库性能,因为查询单表要比关联询多张表 速度要快。
  • 缺点:因为只有当需要用到数据时,才会进行数据库查询,这样在大批量数据查询时,因为查询工作要消耗时 间,所以可能造成用户等待时间变长,造成用户体验下降。
  • 注意:延迟加载是基于嵌套查询来实现的

局部延迟加载

在association和collection标签中都有一个fetchType属性,通过修改它的值,可以修改局部的加载策略。

<resultMap id="userMap" type="user">
	<id column="id" property="id"></id> 
	<result column="username" property="username"></result> 
	<result column="password" property="password"></result> 
	<result column="birthday" property="birthday"></result>
	<!--
		fetchType="lazy" 懒加载策略 
		fetchType="eager" 立即加载策略 
	-->
	<collection property="orderList" ofType="order" column="id" select="com.lagou.dao.OrderMapper.findByUid" fetchType="lazy"> </collection>
</resultMap>
<select id="findAll" resultMap="userMap"> 
	SELECT * FROM `user` 
</select>
  • 在配置了延迟加载策略后,发现即使没有调用关联对象的任何方法,但是在你调用当前对象的equals、clone、hashCode、toString方法时也会触发关联对象的查询。
  • 可以在配置文件中使用lazyLoadTriggerMethods配置项覆盖掉上面四个方法。
<settings> 
	<!--所有方法都会延迟加载--> 
	<setting name="lazyLoadTriggerMethods" value="toString()"/> 
</settings>

全局延迟加载

在Mybatis的核心配置文件中可以使用setting标签修改全局的加载策略。

<settings> 
	<!--开启全局延迟加载功能--> 
	<setting name="lazyLoadingEnabled" value="true"/> 
</settings>

注意:局部的加载策略优先级高于全局的加载策略。

MyBatis缓存

  • 当用户频繁查询某些固定的数据时,第一次将这些数据从数据库中查询出来,保存在缓存中。当用户再次查询这些数据时,不用再通过数据库查询,而是去缓存里面查询。减少网络连接和数据库查询带来的损耗,从而提高我们的查询效率,减少高并发访问带来的系统性能问题。
  • Mybatis中缓存分为一级缓存,二级缓存。

一级缓存

  • 一级缓存是SqlSession级别的缓存,是默认开启的
  • 在参数和SQL完全一样的情况下,我们使用同一个SqlSession对象调用一个Mapper方法,往往只执行一次SQL,因为使用SelSession第一次查询后,MyBatis会将其放在缓存中,以后再查询的时候,如果没有声明需要刷新,并且缓存没有超时的情况下,SqlSession都会取出当前缓存的数据,而不会再次发送SQL到数据库。
    在这里插入图片描述
  • 一级缓存是SqlSession范围的缓存,执行SqlSession的C(增加)U(更新)D(删除)操作,或者调用clearCache()、commit()、close()方法,都会清空缓存。
    在这里插入图片描述
  1. 第一次发起查询用户id为41的用户信息,先去找缓存中是否有id为41的用户信息,如果没有,从数据库 查询用户信息。
  2. 得到用户信息,将用户信息存储到一级缓存中。
  3. 如果sqlSession去执行commit操作(执行插入、更新、删除),清空SqlSession中的一级缓存,这 样做的目的为了让缓存中存储的是最新的信息,避免脏读。
  4. 第二次发起查询用户id为41的用户信息,先去找缓存中是否有id为41的用户信息,缓存中有,直接从缓 存中获取用户信息。

二级缓存

  • 二级缓存是namspace级别(跨sqlSession)的缓存,是默认不开启的
  • 二级缓存的开启需要进行配置,实现二级缓存的时候,MyBatis要求返回的实体对象必须是可序列化的。也就是要求实现Serializable接口,配置方法很简单,只需要在映射XML文件配置 <cache/> 就可以开启二级缓存了。
    在这里插入图片描述
    核心文件
<settings> 
	<!--因为cacheEnabled的取值默认就为true,所以这一步可以省略不配置。 为true代表开启二级缓存;为false代表不开启二级缓存。 --> 
	<setting name="cacheEnabled" value="true"/> 
</settings>

映射文件

<mapper namespace="com.lagou.dao.UserMapper"> 
	<!--当前映射文件开启二级缓存--> 
	<cache></cache> 
	<!--
		<select>标签中设置useCache=”true”代表当前这个statement要使用二级缓存。 
		如果不使用二级缓存可以设置为false 
		注意:针对每次查询都需要最新的数据sql,要设置成useCache="false",禁用二级缓存。 
	--> 
	<select id="findById" parameterType="int" resultType="user" useCache="true" > 
		SELECT * FROM `user` where id = #{id} 
	</select> 
</mapper>
  • 二级缓存是mapper映射级别的缓存,多个SqlSession去操作同一个Mapper映射的sql语句,多个SqlSession可以共用二级缓存,二级缓存是跨SqlSession的。
    在这里插入图片描述
    二级缓存需要执行sqlsession.close()方法才能从一级缓存刷到二级缓存

注意问题(脏读)

  • mybatis的二级缓存因为是namespace级别,所以在进行多表查询时会产生脏读问题,需要使用第三方的缓存技术解决问题。
  • mybatis开启了二级缓存后,那么查询顺序:二级缓存–》一级缓存–》数据库

MyBatis注解

  • @Insert:实现新增,代替了<insert></insert>
  • @Delete:实现删除,代替了<delete></delete>
  • @Update:实现更新,代替了<update></update>
  • @Select:实现查询,代替了<select></select>
  • @Result:实现结果集封装,代替了<result></result>
  • @Results:可以与@Result 一起使用,封装多个结果集,代替了<resultMap></resultMap>
  • @One:实现一对一结果集封装,代替了<association></association>
  • @Many:实现一对多结果集封装,代替了<collection></collection>
public interface UserMapper { 
	@Select("SELECT * FROM `user`") 
	public List<User> findAll(); 
	
	@Insert("INSERT INTO `user`(username,birthday,sex,address) VALUES(#{username},#{birthday},#{sex},#{address})") 
	public void save(User user); 
	
	@Update("UPDATE `user` SET username = #{username},birthday = #{birthday},sex = #{sex},address = #{address} WHERE id = #{id}") 
	public void update(User user); 
	
	@Delete("DELETE FROM `user` where id = #{id}") 
	public void delete(Integer id); }

在这里插入图片描述

一对一查询

a)OrderMapper接口

public interface OrderMapper { 
	@Select("SELECT * FROM orders") 
	@Results({
		@Result(id = true, column = "id", property = "id"), 
		@Result(column = "ordertime", property = "ordertime"), 
		@Result(column = "money", property = "money"), 
		@Result(property = "user", javaType = User.class, column = "uid", one = @One(select = "com.lagou.mapper.UserMapper.findById", fetchType = FetchType.EAGER)) 
	})
		// fetchType = FetchType.EAGER 立即加载策略,不使用延迟加载
	public List<Order> findAllWithUser(); 
}

b)UserMapper接口

public interface UserMapper { 
	@Select("SELECT * FROM `user` WHERE id = #{id}") 
	public User findById(Integer id); 
}

一对多查询

a)UserMapper接口

public interface UserMapper { 
	@Select("SELECT * FROM `user`") 
	@Results({ 
		@Result(id = true, column = "id", property = "id"), 
		@Result(column = "brithday", property = "brithday"), 
		@Result(column = "sex", property = "sex"), 
		@Result(column = "address", property = "address"), 
		@Result(property = "orderList", javaType = List.class, column = "id" , many = @Many(select = "com.lagou.mapper.OrderMapper.findByUid")) 
	})
	public List<User> findAllWithOrder(); 
}

b)OrderMapper接口

public interface OrderMapper { 
	@Select("SELECT * FROM orders WHERE uid = #{uid}") 
	public List<Order> findByUid(Integer uid); 
}

多对多查询

a)UserMapper接口

public interface UserMapper { 
	@Select("SELECT * FROM `user`") 
	@Results({ 
		@Result(id = true, column = "id", property = "id"), 
		@Result(column = "brithday", property = "brithday"), 
		@Result(column = "sex", property = "sex"), 
		@Result(column = "address", property = "address"), 
		@Result(property = "roleList", javaType = List.class, column = "id" , many = @Many(select = "com.lagou.mapper.RoleMapper.findByUid")) 
	})
	public List<User> findAllWithRole(); 
}

b)RoleMapper接口

public interface RoleMapper { 
	@Select("SELECT * FROM role r INNER JOIN user_role ur ON r.`id` = ur.`rid` WHERE ur.`uid` = #{uid}") 
	public List<Role> findByUid(Integer uid); 
}

基于注解的二级缓存

配置SqlMapConfig.xml文件开启二级缓存的支持

<settings> 
	<!--
		因为cacheEnabled的取值默认就为true,所以这一步可以省略不配置。 
		为true代表开启二级缓存;为false代表不开启二级缓存。 
	--> 
	<setting name="cacheEnabled" value="true"/> 
</settings>

在Mapper接口中使用注解配置二级缓存

@CacheNamespace 
public interface UserMapper {...}

注解延迟加载

不管是一对一还是一对多 ,在注解配置中都有fetchType的属性

  • fetchType = FetchType.LAZY 表示懒加载
  • fetchType = FetchType.EAGER 表示立即加载
  • fetchType = FetchType.DEFAULT 表示使用全局配置

注解开发和xml配置优劣分析

  1. 注解开发和xml配置相比,从开发效率来说,注解编写更简单,效率更高。
  2. 从可维护性来说,注解如果要修改,必须修改源码,会导致维护成本增加。xml维护性更强。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值