延迟加载
在一对多的例子中,一个用户加入对应100个账户,但是如果我们只需要用户的信息,那么同时把这100个账户信息也查询出来开销是非常大的。所以在查询信息的时候,我们需要弄明白 需要什么信息,什么时候需要。
- 延迟加载:
1.在真正使用数据时才发起查询,不用的时候不查询。按需查询(懒加载)
2.在多对多,一对多关系中,通常情况下使用延迟加载 - 立即加载:
1.不管用不用,只要调用方法,马上发起查询
2.在多对一,一对一关系中,通常情况下使用立即加载
一对一实现延迟加载
要实现延迟加载,需要在配置文件中设置两个参数:
- SqlMapConfig.xml
<!-- 配置参数 configuration标签下-->
<settings>
<!-- 开启延迟加载-->
<setting name="lazyLoadingEnabled" value="true"/>
<!-- 开启方法触发延迟加载 按需加载【而不是全部都是延迟加载】,3.4.1之后默认为false-->
<setting name="aggressiveLazyLoading" value="false"/>
</settings>
配置好参数之后,在IAccountDao.xml中调用IUserDao.xml中的findById方法即可。
<resultMap id="accountUserMap" type="domain.account">
<id property="id" column="id"></id>
<result property="uid" column="uid"></result>
<result property="money" column="money"></result>
<!-- 一对一的封装映射,也就是封装user的内容
select 属性指定的内容,查询用户的唯一标识
column指定的属性,用户根据id查询时,所需要的参数的值
-->
<association property="user" column="uid" javaType="domain.User" select="dao.IUserDao.findById">
</association>
</resultMap>
<!-- 查询所有-->
<select id="findAll" resultMap="accountUserMap">
select * from account;
</select>
之后我们可以发现,Account中的User列表只在输出时,查询:
一对多实现延迟加载
方法和一对一基本相同,配置好参数后,在IUserDao.xml中调用IAccountDao.xml的findById方法,不同的是,这次要用collection标签
- IUserDao.xml:
<resultMap id="findAllRole" type="domain.User">
<id property="id" column="id"></id>
<result property="username" column="username"></result>
<result property="sex" column="sex"></result>
<result property="address" column="address"></result>
<result property="birthday" column="birthday"></result>
<!-- 注意使用 collection 标签 -->
<collection property="accounts" ofType="domain.account" select="dao.IAccountDao.findById" column="id">
</collection>
</resultMap>
<select id="findAll" resultMap="findAllRole">
select * from user;
</select>
缓存
- 缓存:存在于内存中的临时数据。
- 用处:减少和数据库的交互次数,提高执行效率。
- 范围:经常查询并且不经常改变,同时数据的正确与否对最终结果影响不大的数据。
一级缓存
Mybatis中sqlSession对象的缓存。
当我们执行查询之后,查询的结果会同时存放于SqlSession提供的一块区域中。该区域的结构是一个Map,存放的是对象。当我们再次查询同样的数据,mybatis会先去SqlSession中查询是否有,有的话直接拿来用。
当SqlSession对象消失时,mybatis的一级缓存也就消失了。
- 清空缓存:一级缓存是SqlSession范围的缓存,当调用SqlSession的修改,添加,删除,commit(),close(),clearCache()等方法时,就会清空一级缓存。
二级缓存
Mybatis中SqlSessionFactory对象的缓存。由同一个SqlSessionFactory创建的SqlSession共享其缓存。
二级缓存存放的是数据,不是对象。
二级缓存的使用步骤:
- 让Mybatis框架支持二级缓存(在SqlMapConfig.xml中配置)
<settings>
<!-- 开启缓存 默认是true-->
<setting name="cacheEnabled" value="true"/>
</settings>
- 让当前的映射文件支持二级缓存(在IUserDao.xml中配置)
<mapper namespace="cn.ykf.mapper.UserMapper">
<!-- 使用缓存 -->
<cache/>
</mapper>
- 让当前的操作支持二级缓存(在select标签中配置)
<select id="listAllUsers" resultMap="UserWithAccountsMap" useCache="true">
SELECT * FROM user
</select>
注解开发
在mybatis中针对crud,一共有四个注解
注解 | 作用 |
---|---|
@Select | 查询 |
@Insert | 插入 |
@Update | 更新 |
@Delete | 删除 |
单表查询
注解开发只需要在接口方法上写注解即可实现:
package dao;
import domain.User;
import org.apache.ibatis.annotations.Delete;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update;
import java.util.List;
public interface IUserDao {
/**
* 查询所有用户
* @return
*/
@Select("select * from user")
List<User> findAll();
/**
* 保存用户
* @param user
*/
@Insert("insert into user(username,address,sex,birthday) values(#{username},#{address},#{sex},#{birthday})")
void saveUser(User user);
/**
* 更新用户
* @param user
*/
@Update("update user set username = #{username},address=#{address},sex=#{sex},birthday=#{birthday} where id = #{id}")
void updateUser(User user);
/**
* 删除用户
* @param id
*/
@Delete("delete from user where id = #{id}")
void delete(Integer id);
/**
* 根据id查询用户
* @param id
* @return
*/
@Select("select * from user where id = #{id}")
User findOneById(Integer id);
/**
* 根据名字查询用户
* @param username
* @return
*/
@Select("select * from user where username like '%${value}%'")
List<User> findByName(String username);
/**
* 查询所有
* @return
*/
@Select("select count(*) from user")
int findTotal();
}
如果属性名和列名不同,可以使用Results和ResultMap注解。
/**
* 查询所有用户
* @return
*/
@Select("select * from user")
@Results(id = "userMap",value = {
@Result(id = true,column = "id",property = "id"),
@Result(column = "username",property = "username"),
@Result(column = "sex",property = "sex"),
@Result(column = "address",property = "address"),
@Result(column = "birthday",property = "birthday"),
})
List<User> findAll();
/**
* 保存用户
* @param user
*/
@Insert("insert into user(username,address,sex,birthday) values(#{username},#{address},#{sex},#{birthday})")
@ResultMap("userMap")
void saveUser(User user);
多表查询
多对一
在Results注解中有 @One注解用来执行子查询返回单一对象
/**
* 查询所有账户,并且获取对应用户信息
* @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 = "dao.IUserDao.findOneById",fetchType = FetchType.EAGER))
})
List<Account> findAll();
一对多
/**
* 查询所有用户
* @return
*/
@Select("select * from user")
@Results(id = "userMap",value = {
@Result(id = true,column = "id",property = "id"),
@Result(column = "username",property = "username"),
@Result(column = "sex",property = "sex"),
@Result(column = "address",property = "address"),
@Result(column = "birthday",property = "birthday"),
@Result(property = "accounts",column = "id",many = @Many(select = "dao.IAccountDao.findById",fetchType = FetchType.LAZY))
})
List<User> findAll();
注解使用二级缓存
在Mybatis中开启全局配置:
<settings>
<!-- 开启缓存 -->
<setting name="cacheEnabled" value="true"/>
</settings>
在持久层接口使用注解:
@CacheNamespace(blocking = true)
public interface UserMapper {
// .....
}