MyBatis高级操作

01_MyBatis的延迟加载

  • 何为延迟加载
    Mybatis可以进行多表查询,实现对象的关联查询。而在实际开发过程中很多时候我们并不需要在加载用户信息时就一定要加载他的订单信息。此时就是我们所说的延迟加载。

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

  • 好处
    先从单表查询,需要时再从关联表去关联查询,大大提高数据库性能,因为查询单表要比关联查询多张表速度要快。

  • 应用
    通常情况下,一对一查询不需要做延迟加载,一对多需要做延迟加载

02_一对一延迟加载实现

  • 使用前提
    需要在sqlMapConfig.xml配置文件中开启延迟加载
<settings>
<setting name="lazyLoadingEnabled" value="true"/>
</settings>
  • 需求:
    通过订单延迟加载相应的用户信息

  • POJO类

public class Customer {

	private Long cid;
	private String cname;
	private int cage;
	//get/set方法
}
public class Order {

	private Long oid;
	private String oname;
	private Customer customer;
	private Integer cno;
	//get/set方法
}
  • 映射文件
<!‐‐ 
订单映射文件
select属性:查询用户信息延迟加载的实现
column属性:查询用户信息需要传递的参数,该参数从先加载的订单信息中获取.
‐‐>
<mapper namespace="com.aaa.dao.IOrderDao">
	<resultMap type="com.aaa.bean.Order" id="orderCustomerMap">
		<id property="oid" column="oid"/>
		<result property="oname" column="oname"/>
		<association
			property="customer"
			javaType="com.aaa.bean.Customer"
			select="com.aaa.dao.ICustomerDao.selectCustomerById"
			column="cno">
		</association>
	</resultMap>

	<select id="selectOrderList" resultMap="orderCustomerMap">
		select * from tb_order;
	</select>
</mapper>

<!‐‐ 用户映射文件 ‐‐>
<select id="selectCustomerById" parameterType="int" resultType="com.aaa.bean.Customer">
	select * from tb_customer where cid = #{id};
</select>
  • 测试
@Test
public void selectOrderList(){
	List<Order> list = orderDao.selectOrderList();
	//会触发查询用户信息
	list.get( 0 ).getCustomer();
}

03_一对多延迟加载实现

  • 需求:
    通过用户信息延迟加载相应的订单信息

  • POJO类

public class Customer {

	private Long cid;
	private String cname;
	private int cage;
	private List<Order> list;
	//get/set方法
}

public class Order {

	private Long oid;
	private String oname;
	private Customer customer;
	private Integer cno;
	//get/set方法
}
  • 映射文件
<!‐‐
用户映射文件
select属性:查询订单信息延迟加载实现
column属性:查询订单信息需要传递的参数,得先从已经加载的用户信息中获取
‐‐>
<resultMap type="com.aaa.bean.Customer" id="customerOrderMap">
	<id property="cid" column="cid" />
	<result property="cname" column="cname" />
	<result property="cage" column="cage" />
	<collection
		property="list"
		ofType="com.aaa.bean.Order"
		select="com.aaa.dao.IOrderDao.selectOrderListByCustomerId"
		column="cid"></collection>
</resultMap>

<select id="selectCustomerById" parameterType="long" resultMap="customerOrderMap">
	select * from tb_customer where cid = #{id};
</select>

<!‐‐ 
订单映射文件
‐‐>
<select id="selectOrderListByCustomerId" parameterType="long"
resultMap="orderCustomerMap">
	select * from tb_order where cno = #{cno};
</select>
  • 测试
Customer customer = customerDao.selectCustomerById(1L);
System.out.println(customer.getCname());
System.out.println(customer.getList());

04_MyBatis的缓存

  • 什么是缓存?
    存储在内存中的临时数据

  • 为什么使用缓存?
    减少和数据库的交互次数,提高执行效率

  • 应用场景

  1. 适用于缓存
    经常查询并且不经常改变的
    数据的正确与否对最终结果影响不大

  2. 不适用于缓存
    数据经常改变的
    数据的正确与否对最终结果影响不大

  3. 比如:
    商品库存,银行汇率…

05_一级缓存的验证

  • 概念
    一级缓存是 SqlSession 范围的缓存,当调用 SqlSession 的修改,添加,删除, commit(),close()等方法时,就会清空一级缓存。
  • 验证
public interface IUserDao {
	public User selectUserById(Long id);
}

<mapper namespace="com.aaa.dao.IUserDao">
	<select id="selectUserById" parameterType="long" resultType="com.aaa.bean.User">
		select * from user where id = #{id};
	</select>
</mapper>

@Test
public void selectUserById() throws IOException{
	InputStream inputStream = Resources.getResourceAsStream("sqlMapConfig.xml");
	SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
	SqlSession session = sessionFactory.openSession();
	IUserDao userDao = session.getMapper(IUserDao.class);
	User user1 = userDao.selectUserById( 2 l);
	session.clearCache();
	User user2 = userDao.selectUserById( 2 l);
	System.out.println(user1 == user2);
}

05_增删改清空一级缓存

  • 概念
    如果 sqlSession去执行commit操作(执行插入、更新、删除),清空 SqlSession中的一级缓存,这样做的目的为了让缓存中存储的是最新的信息

  • 以修改操作为例:

InputStream inputStream = Resources.getResourceAsStream("sqlMapConfig.xml");
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession session = sessionFactory.openSession();
IUserDao userDao = session.getMapper(IUserDao.class);
User user1 = userDao.selectUserById(2l);
userDao.updateUser(new User(3l, "aaaa", "aa"));
User user2 = userDao.selectUserById(2l);
System.out.println(user1 == user2);
session.commit();
session.close();

06_MyBatis的二级缓存

  • 概念
    二级缓存是 mapper 映射级别的缓存,多个 SqlSession 去操作同一个 Mapper 映射的 sql语句,多个SqlSession 可以共用二级缓存,二级缓存是跨 SqlSession 的。

  • 使用步骤

  1. 开启二级缓存
<settings>
	<!‐‐ 开启缓存的支持 ‐‐>
	<setting name="cacheEnabled" value="true"/>
</settings>
  1. 在mapper映射文件配置标签
<mapper namespace="com.aaa.dao.IUserDao">
	<!‐‐ 开启二级缓存的支持 ‐‐>
	<cache></cache>
</mapper>
  1. 配置statement上面的useCache属性
<!‐‐设置 useCache=”true”代表当前这个 statement 要使用二级缓存,如果不使用二级缓存可以设置为 false。‐‐>
<select id="findById" resultType="user" parameterType="int" useCache="true">
    select * from user where id = #{uid}
</select>
  • 注意事项
    二级缓存存储的并不是java对象,存储的是对象所对应的字符串信息,当从二级缓存取出时,根据对应字符串生成新的对象,所以,使用二级缓存,会发现取出对象是不同的对象。但是,sql语句只执行了一次。

  • 测试代码

@Test
public void selectUserById() throws IOException{
	InputStream inputStream = Resources.getResourceAsStream("sqlMapConfig.xml");
	SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
	SqlSession session = sessionFactory.openSession();
	IUserDao userDao = session.getMapper(IUserDao.class);
	User user1 = userDao.selectUserById(2l);
	//销毁第一次查询的一级缓存,否则会报错
	session.close();
	session = sessionFactory.openSession();
	userDao = session.getMapper(IUserDao.class);
	User user2 = userDao.selectUserById(2l);
	//销毁第二次查询的一级缓存
	session.close();
	System.out.println(user1 == user2);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值