一、延迟加载
什么是延迟加载
resultMap中的association和collection标签具有延迟加载的功能。
延迟加载的意思是说,在关联查询时,利用延迟加载,先加载主信息。需要关联信息时再去按需加载关联信息。这样会大大提高数据库性能,因为查询单表要比关联查询多张表速度要快。
设置延迟加载
Mybatis默认是不开启延迟加载功能的,我们需要手动开启。
需要在SqlMapConfig.xml文件中,在<settings>标签中开启延迟加载功能。
lazyLoadingEnabled、aggressiveLazyLoading
设置项 | 描述 | 允许值 | 默认值 |
lazyLoadingEnabled | 全局性设置懒加载。如果设为‘false’,则所有相关联的都会被初始化加载。 | true | false | false |
aggressiveLazyLoading | 当设置为‘true’的时候,懒加载的对象可能被任何懒属性全部加载。否则,每个属性都按需加载。 | true | false | true |
1在SqlMapConfig.xml中配置延迟加载
2在OrderMapper.xml中设置sql语句(按需加载)
3创建OrderMapper接口
4创建Usermapper接口
5创建Usermapper.xml
6测试
//1在SqlMapConfig.xml中配置延迟加载
<!--开启延迟加载的功能-->
<settings>
<!--lazyLoadingEnabled :延迟加载启动 默认是false-->
<setting name="lazyLoadingEnabled" value="true"/>
<!--aggressiveLazyLoading:默认是true,就是积极加载, false按需加载,需要的时候再加载-->
<setting name="aggressiveLazyLoading" value="false"/>
</settings>
//2在OrderMapper.xml中设置sql语句(按需加载)
<resultMap id="OrderUserLazyLoadingMap" type="com.javacto.po.Orders">
<id column="id" property="id"></id>
<result column="order_Number" property="orderNumber"></result>
<result column="createtime" property="createtime"></result>
<result column="describer" property="describer"></result>
<result column="user_id" property="userId"></result>
<!--通过 user_id关联查询出用户信息,按需加载
select 就是我们的
column:传过去的值
-->
<association property="user" select="com.javacto.mapper.UserMapper.findById" column="user_id">
</association>
</resultMap>
<!--查询订单信息,并关联查询出用户信息-->
<select id="queryOrderUserLazyLoadingMap" resultMap="OrderUserLazyLoadingMap">
SELECT * FROM orders
</select>
//3创建OrderMapper接口
//查询订单信息,并关联查询出用户信息
public List<Orders> queryOrderUserLazyLoadingMap();
//4创建Usermapper接口
public interface UserMapper {
public User findById(int uid);
}
//5创建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">
<!--namespace :命名空间,必需是接口全限定名-->
<mapper namespace="com.javacto.mapper.UserMapper">
<select id="findById" parameterType="int" resultType="User">
SELECT * FROM t_user WHERE tid=#{tid }
</select>
</mapper>
//6测试
//3.查询用户信息及用户购买的商品信息,多对多
@Test
public void testqueryOrderUserLazyLoadingMap(){
//1.创建SqlSession
SqlSession sqlSession = sqlSessionFactory.openSession();
//2。
OrderMapper orderMapper =sqlSession.getMapper(OrderMapper.class);
//3.调用方法
List<Orders> list = orderMapper.queryOrderUserLazyLoadingMap();
for(Orders o:list){
//这里我没有显示用户的信息,就没有查询
System.out.print(o.getId());
System.out.println(o.getDescriber());
//现在想显示用户信息,
System.out.println(o.getUser());
}
sqlSession.close();
}
二、缓存
mybatis缓存分析
mybatis提供查询缓存,如果缓存中有数据就不用从数据库中获取,用于减轻数据压力,提高系统性能。
一级缓存是SqlSession级别的缓存。在操作数据库时需要构造 sqlSession对象,在对象中有一个数据结构(HashMap)用于存储缓存数据。不同的sqlSession之间的缓存数据区域(HashMap)是互相不影响的。
二级缓存是mapper级别的缓存,多个SqlSession去操作同一个Mapper的sql语句,多个SqlSession可以共用二级缓存,二级缓存是跨SqlSession的
一、一级缓存
第一次发起查询用户id为1的用户信息,先去找缓存中是否有id为1的用户信息,如果没有,从数据库查询用户信息。
得到用户信息,将用户信息存储到一级缓存中。
如果sqlSession去执行commit操作(执行插入、更新、删除),清空SqlSession中的一级缓存,这样做的目的为了让缓存中存储的是最新的信息,避免脏读
第二次发起查询用户id为1的用户信息,先去找缓存中是否有id为1的用户信息,缓存中有,直接从缓存中获取用户信息。
Mybatis默认支持一级缓存。
二、二级缓存
下图是多个sqlSession请求UserMapper的二级缓存图解。
二级缓存是mapper级别的。
第一次调用mapper下的SQL去查询用户信息。查询到的信息会存到该mapper对应的二级缓存区域内。
第二次调用相同namespace下的mapper映射文件中相同的SQL去查询用户信息。会去对应的二级缓存内取结果。
如果调用相同namespace下的mapper映射文件中的增删改SQL,并执行了commit操作。此时会清空该namespace下的二级缓存。
开启二级缓存
在核心配置文件SqlMapConfig.xml中加入以下内容(开启二级缓存总开关):
1在settings标签中添加以下内容:
<settings>
<!--开启二级缓存-->
<setting name="cacheEnabled" value="true"/>
</settings>
2在UserMapper映射文件中,加入以下内容,开启二级缓存:
<?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">
<!--namespace :命名空间,必需是接口全限定名-->
<mapper namespace="com.javacto.mapper.UserMapper">
<!--哪个mapper需要使用, 就在哪个mapper中加cache-->
<cache ></cache>
<select id="findById" parameterType="int" resultType="User">
SELECT * FROM t_user WHERE tid=#{tid }
</select>
<!--添加用户
parameterType 我们需要传参数,参数类型是什么? 对象
-->
<insert id="insertUser" parameterType="com.javacto.po.User">
INSERT INTO t_user VALUES(#{tid},#{uname},now(),#{sex},#{address})
</insert>
</mapper>
3实现序列化
由于二级缓存的数据不一定都是存储到内存中,它的存储介质多种多样,所以需要给缓存的对象执行序列化。
如果该类存在父类,那么父类也要实现序列化。
三、注解开发
第一步.Mapper配置类指定接口
<mapper class="com.javacto.day01.UserMapper2"></mapper>
第二步、接口
public interface UserMapper2 {
//以一起使用注解,同时可以使用xml 我可以再创建一个 UserMapper2.xml
//根据查询
@Select("SELECT * FROM t_user WHERE tid=#{tid }")
public User findUserById002(@Param("tid") int tid);
//模糊查询
@Select("SELECT * FROM TUSER WHERE uname LIKE concat(concat('%',#{uname}),'%')")
public List<User> findByName(String uname);
//查询所有
@Select("SELECT * FROM TUSER")
public List<User> findUserList();
//添加
@Insert("INSERT INTO t_user VALUES(#{tid},#{uname},now(),#{sex},#{address})")
public int insertUser(User user);
//删除
@Delete("DELETE FROM TUSER WHERE tid=${id}")
public int deleteUser(@Param(("id")) int id);
}
第三步、测试
public class UserMapper2Test002 {
//因为现在测试,这里还是有些代码, 以后都不用写
SqlSessionFactory sqlSessionFactory =null;
@Before
public void setUp() throws IOException {
//1.获取SqlMapConfig.xml
String path = "SqlMapConfig.xml";
//import org.apache.ibatis.io.Resources; 一定不要导错包
InputStream is = Resources.getResourceAsStream(path);
//2.创建SqlSessionFactory 我可不可以定义一全局的
sqlSessionFactory= new SqlSessionFactoryBuilder().build(is);
}
@Test
public void testqueryOrderAndUserRetType(){
//1.创建SqlSession
SqlSession sqlSession = sqlSessionFactory.openSession();
//2。
UserMapper2 userMapper2 =sqlSession.getMapper(UserMapper2.class);
//3.调用方法
User user = userMapper2.findUserById002(1001);
System.out.println(user);
sqlSession.close();
}
}