目录
延时加载
概念:当我们查询一些信息时,我们需要的部分进行查询,而暂时不需要的部分不进行查询,从而减轻数据库查询压力
实现:
需要在sqlMapConfig中设置延迟加载相关配置,即前两项
<setting name="cacheEnabled" value="true"/>
<setting name="lazyLoadingEnabled" value="true"/>
缓存
分为一级缓存和二级缓存:
一级缓存在sqlSession域中,当sqlSession没有执行close或是commit方法时,sqlSession会开辟一个缓存域,该域的结构是一个Map,当我们查询同样的数据,mybatis会先去sqlSession中查询是否有,有的话直接拿来用。其所取的是对象。所以两种==返回true。
二级缓存在sqlSessionFactory中,同一个sqlSessionFactory的openSession里,访问相同数据源会先查看有无缓存,有的话直接拿来用。
二级缓存的相关配置:
<setting name="cacheEnabled" value="true"/>
同时在相关Dao.xml配置文件中加入(这里我们以一个UserDao的findById方法举例):
<?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.yz.dao.UserDaoImp"><!--这里的namespace对于Dao中接口的位置-->
<!--令Dao支持二级缓存-->
<cache/>
<!--这里注意将useCache设为true-->
<select id="findById" parameterType="int" resultType="User" useCache="true">
select *
from new_user
where id like #{uid};
</select>
</mapper>
写一个测试方法:
@Test
public void testCache(){
SqlSession session1=factory.openSession();
UserDaoImp daoImp1=session1.getMapper(UserDaoImp.class);
User user1=daoImp1.findById(1);
System.out.println(user1);
session1.close();
SqlSession session2=factory.openSession();
UserDaoImp daoImp2=session2.getMapper(UserDaoImp.class);
User user2=daoImp2.findById(1);
System.out.println(user2);
session1.close();
System.out.println(user1==user2);
}
用同一个factory创建不同的sqlSession,去查找同一个对象;会发现user1进行了查询,而user2会直接返回缓存中的内容 。(这里要注意,虽然最后返回的为false,但并不代表两次查找的对象不同,而是缓存中储存的是数据而不是对象,其信息是相同的但无法进行比较)
注解开发
即在Dao接口的方法上使用:@Select(),@Update(),@Insert(),@Delete();后面的括号写上对应的sql语句。
疑惑解答1:为什么在注解里写sql语句就实现了xml配置开发的相同功能?
在这里依然以UserDaoImp的查询所有方法为例进行解析:
package com.yz.dao;
import com.yz.domain.User;
import org.apache.ibatis.annotations.Select;
import java.util.List;
public interface UserDaoImp {
@Select("select * from new_user")
List<User> findAll();
}
<select id="findAll" resultType="com.yz.domain.User"><!--这里必须注意要指定查询结果的封装对象resultType-->
SELECT * from new_user
</select>
通过对比,我们可以发现在xml中的信息,在dao接口均可获得:
- id ---> findAll 方法名
- resultType ---> <User>
- sql语句 ---> @Select("select * from new_user")
所以注解开发仅写入sql语句就可以到达xml配置相同的功能了,这里要注意:这两种方式不能同时存在和使用,否则会导致Mybatis无法识别你要用那种配置,导致报错
疑惑解答2:注解开发如何解决类属性名和表列名不对应的情况?
mybatis给我提供了相关的方法:
@Select("sql语句")
@Results(value = {
@Result(id = true,column = "",property = ""),
@Result(id = false,column = "",property = ""),
@Result(id = false,column = "",property = ""),
@Result(id = false,column = "",property = ""),
@Result(id = false,column = "",property = "")
}/*若不为属性不为id,则id=false可省略,因为其默认值就是false*/
@Results(id = "userMap", value = {
@Result(id = true,column = "",property = ""),
@Result(id = false,column = "",property = ""),
@Result(id = false,column = "",property = ""),
@Result(id = false,column = "",property = ""),
@Result(id = false,column = "",property = "")
}/*若不为属性不为id,则id=false可省略,因为其默认值就是false*/
)
@Select("sql语句")
@ResultMap("userMap")
上述两种均可使用。
补充:注解开发的一对一,一对多查询配置
1)一对一:依然以一个账户对应一个用户为例说明:
public interface AccountDaoImp {
/**
* 查询所有的账号
* @return
*/
@Select("select * from account")
@Results(id = "accountMap",value = {
@Result(id = true,column = "id",property = "id"),
@Result(column = "uid",property = "uid"),
@Result(column = "money",property = "money"),
@Result(property = "user",column = "uid",one = @One(select = "com.yz.dao.UserDaoImp.findById",fetchType = FetchType.EAGER))/*一对一查询一般设置其为快加载*/
})
List<Account> findAll();
}
public interface UserDaoImp {
@Select("select * from new_user")
@Results(id = "userMap", value = {
@Result(id = true,column = "id",property = "id"),
@Result(id = false,column = "username",property = "username"),
@Result(id = false,column = "birthday",property = "birthday"),
@Result(id = false,column = "sex",property = "sex"),
@Result(id = false,column = "address",property = "address"),
} )/*若不为属性不为id,则id=false可省略,因为其默认值就是false*/
List<User> findAllByAnnotation();
@Select("select * from new_user where id =#{id}")
@ResultMap("userMap")
User findById(int id);
}
2)一对多:以一个用户有多个账户为例说明:
@CacheNamespace(blocking = true)//这里是开启二级缓存
public interface UserDaoImp {
/**
* 基于注解进行查询
*/
@Select("select * from new_user")
@Results(id = "userMap", value = {
@Result(id = true,column = "id",property = "id"),
@Result(id = false,column = "username",property = "username"),
@Result(id = false,column = "birthday",property = "birthday"),
@Result(id = false,column = "sex",property = "sex"),
@Result(id = false,column = "address",property = "address"),
@Result(property = "accounts",column = "id",many = @Many(select = "com.yz.dao.AccountDaoImp.findByUId",fetchType = FetchType.LAZY))/*一对多一般用懒加载*/
} )/*若不为属性不为id,则id=false可省略,因为其默认值就是false*/
List<User> findAllByAnnotation();
}
public interface AccountDaoImp {
/**
* 根据uid查询账户
* @param uid
* @return
*/
@Select("select * from account where uid = #{uid}")
List<Account> findByUId(Integer uid);
}