mybatis-注解
Posted 拾亿~
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了mybatis-注解相关的知识,希望对你有一定的参考价值。
mybatis延迟加载
延迟加载:
- 就是在需要用到数据时才进行加载,不需要用到数据时就不加载数据。延迟加载也称懒加载.
- 好处:先从单表查询,需要时再从关联表去关联查询,大大提高数据库性能,因为查询单表要比关联查询多张表速度要快。
- 坏处: 因为只有当需要用到数据时,才会进行数据库查询,这样在大批量数据查询时,因为查询工作也要消耗时间,所以可能造成用户等待时间变长,造成用户体验下降。
Mybatis延迟加载实现:
-
在主配置文件mybatis-config.xml中添加:
<!-- 配置参数--> <settings> <!-- 开启MyBatis延迟加载--> <setting name="lazyLoadingEnabled" value="true"/> <setting name="aggressiveLazyLoading" value="false"/> </settings>
注意:
标签必须在 标签和 标签之间。
mybatis缓存
缓存:像大多数的持久化框架一样,Mybatis 也提供了缓存策略,通过缓存策略来减少数据库的查询次数,从而提高性能。
Mybatis 中缓存分为一级缓存,二级缓存。
一级缓存
一级缓存:
- 一级缓存是 SqlSession级别的缓存,只要SqlSession 没有 flush或 close,它就存在。
- 一级缓存是 SqlSession范围的缓存,当调用 SqlSession 的修改,添加,删除,commit(),close()等方法时,就会清空一级缓存。
执行流程:
- 第一次发起查询用户 id 为 1 的用户信息,先去找缓存中是否有 id 为 1 的用户信息,如果没有,从数据库查询用户信息。
- 得到用户信息,将用户信息存储到一级缓存中。
- 如果 sqlSession去执行commit 操作(执行插入、更新、删除),清空 SqlSession 中的一级缓存,这样做的目的为了让缓存中存储的是最新的信息,避免脏读。
- 第二次发起查询用户 id 为 1 的用户信息,先去找缓存中是否有 id 为 1 的用户信息,缓存中有,直接从缓存中获取用户信息。
二级缓存
二级缓存:
- 二级缓存是 mapper 映射级别的缓存,多个 SqlSession 去操作同一个 Mapper 映射的 sql 语句,多个SqlSession可以共用二级缓存,二级缓存是跨 SqlSession 的。
执行流程:
- 首先开启 mybatis的二级缓存。
- sqlSession1 去查询用户信息,查询到用户信息会将查询数据存储到二级缓存中。
- 如果 SqlSession3 去执行相同 mapper映射下 sql,执行 commit 提交,将会清空该 mapper 映射下的二级缓存区域的数据。
- sqlSession2 去查询与 sqlSession1 相同的用户信息,首先会去缓存中找是否存在数据,如果存在直接从缓存中取出数据。
配置二级缓存:
-
在主配置文件中配置:
<!--因为 cacheEnabled 的取值默认就为 true,所以这一步可以省略不配置。为 true 代表开启二级缓存;为false代表不开启二级缓存。--> <settings> <!-- 开启二级缓存的支持 --> <setting name="cacheEnabled" value="true"/> </settings>
-
在映射文件中使用二级缓存:
<?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.mybatis_xml.mapper.IUserMapper"> <!-- 开启二级缓存的支持:cache标签表示当前这个mapper映射将使用二级缓存,区分的标准就看 mapper 的 namespace值--> <cache></cache> <!--在<select>标签中使用userCache="true"使用二级缓存--> <select id="findAll" resultType="user" userCache="true"> select * from user </select> </mapper>
使用二级缓存注意事项:
- 当我们在使用二级缓存时,所缓存的类一定要实现java.io.Serializable 接口,这样就可以使用序列化方式来保存对象。
mybatis注解
常用注解
- @Insert:实现新增
- @Update:实现更新
- @Delete:实现删除
- @Select:实现查询
- @Result:实现结果集封装
- @Results:可以与@Result一起使用,封装多个结果集
- @ResultMap:实现引用@Results 定义的封装
- @One:实现一对一结果集封装
- @Many:实现一对多结果集封装
- @SelectProvider: 实现动态SQL映射
- @CacheNamespace:实现注解二级缓存的使用
复杂映射注解介绍
- @Results注解:代替了
标签,实现实体类和表的映射关系。 - 该注解中可以使用单个@Result注解,也可以使用@Result集合:
@Results({@Result(),@Result()})
- 该注解中可以使用单个@Result注解,也可以使用@Result集合:
- @Resutl 注解:代替了
标签和 标签 ,实现实体类属性和表字段的映射关系。 - id属性:是否是主键
- column属性:数据库表中的列名
- property属性:对应实体类的属性名
- one属性:表示一对一关系:
@Result(one=@One())
- many属性:表示多对一关系:
@Result(many=@many())
- @One注解(一对一):代替了
标签,是多表查询的关键,在注解中用来指定子查询返回单一对象。 @Result(column=" ",property="",one=@One(select=""))
- select属性:子查询所在的接口方法的全限定名。
- @Result注解的column属性:指定传递到子查询所在的接口方法中参数,一般为外键。注意:是数据库的列名。
- @Result注解的property属性:指定子查询返回的实体对象。一般为被引用的实体类的对象。
- fetchType属性:会覆盖全局的配置参数 lazyLoadingEnabled。
- @Many注解(多对一):代替了
标签,是多表查询的关键,在注解中用来指定子查询返回对象集合。 @Result(property="",column="",many=@Many(select=""))
- select属性:指定用来子查询的 sqlmapper。
- @Result注解的column属性:指定传递到子查询所在的接口方法中参数,一般为主键。注意:是数据库的列名。
- @Result注解的property属性:指定子查询返回的实体对象集合。一般为被引用的实体类的对象集合。
- fetchType属性:会覆盖全局的配置参数 lazyLoadingEnabled。
一对一查询
注意:一对一的实体类,数据库表,参考一对一查询(上方)。
player表:pid,pname,psex
game_account表:gid,gusername,gpassword,gpid(player主键)
Playe实体类:pid,pname,psex
GameAccount实体类:gid,gusername,gpassword,gpid(player主键),player(player实体类的引用)
格式:
@Result(column="外键",property="被引用对象",one=@One(select="子查询所在的接口方法的全限定名"))
IPlayerMapper接口:基于注解配置
package com.mybatis_anno.mapper;
import com.mybatis_anno.pojo.Player;
import org.apache.ibatis.annotations.Select;
public interface IPlayerMapper {
@Select("select * from player where pid=#{pid}")
Player findById(Integer playerId);
}
//注意:Player的信息为关联查询的信息,所以IPlayerMapper接口就是关联查询接口,findById就是关联查询的方法,playerId对应的pid就是column的值
IGameAccountMapper接口:基于注解配置
package com.mybatis_anno.mapper;
import com.mybatis_anno.pojo.GameAccount;
import org.apache.ibatis.annotations.One;
import org.apache.ibatis.annotations.Result;
import org.apache.ibatis.annotations.Results;
import org.apache.ibatis.annotations.Select;
import java.util.List;
public interface IGameAccountMapper {
//账号和玩家为一对一关系;查询账号,关联查询玩家
@Select("select * from game_account")
@Results(id = "gameAccountMap",value = {
@Result(id = true,column = "gid",property = "gid"),
@Result(column = "gusername",property = "gusername"),
@Result(column = "gpassword",property = "gpassword"),
@Result(column = "gpid",property = "gpid"),
// 配置一对一
@Result(property = "player",column = "gpid",one = @One(select = "com.mybatis_anno.mapper.IPlayerMapper.findById"))
})
List<GameAccount> findAll();
}
多对一查询
注意:多对一的实体类,数据库表,参考多对一查询(上方)。
own表:oid,oname
book表:bid,bname,boid(own表主键)
Own实体类:oid,oname,books(Book实体类集合的引用)
Book实体类:bid,bname,boid(own表主键)
格式:
@Result(column = "子查询的参数",property = "子查询返回实体对象的集合",many = @Many(select = "子查询所在的接口方法的全限定名"))
IBookMapper接口:
package com.mybatis_anno.mapper;
import com.mybatis_anno.pojo.Book;
import org.apache.ibatis.annotations.Select;
import java.util.List;
public interface IBookMapper {
//本方法通过外键查询
@Select("select * from book where boid=#{boid}")
List<Book> findByBid(Integer ownId);
}
IOwnMapper接口:
package com.mybatis_anno.mapper;
import com.mybatis_anno.pojo.Own;
import org.apache.ibatis.annotations.*;
import java.util.List;
public interface IOwnMapper {
//多对一|一对多:查询所有者,关联查询书籍
@Select("select * from own")
@Results(id = "ownMap",value = {
@Result(id = true,column = "oid",property = "oid"),
@Result(column = "oname",property = "oname"),
// 配置多对一
@Result(column = "oid",property = "books",many = @Many(select = "com.mybatis_anno.mapper.IBookMapper.findByBid"))
})
List<Own> findAll();
}
二级缓存
-
开启二级缓存:
<!-- 配置二级缓存 --> <settings> <!-- 开启二级缓存的支持 --> <setting name="cacheEnabled" value="true"/> </settings>
-
注解配置缓存:
- 在接口上配置:@CacheNamespace(blocking=true)//mybatis 基于注解方式实现配置二级缓存
@CacheNamespace(blocking=true) public interface ITestMapper{ }
以上是关于mybatis-注解的主要内容,如果未能解决你的问题,请参考以下文章