一、xml中重要的标签
1.1、where标签
查询条件实体类
public class QueryTeamVO {
private String name;
private Date beginTime;
private Date endTime;
private String location;
public QueryTeamVO() {
}
public QueryTeamVO(String name, Date beginTime, Date endTime, String location) {
this.name = name;
this.beginTime = beginTime;
this.endTime = endTime;
this.location = location;
}
@Override
public String toString() {
return "QueryTeamVO{" +
"name='" + name + '\'' +
", beginTime=" + beginTime +
", endTime=" + endTime +
", location='" + location + '\'' +
'}';
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Date getBeginTime() {
return beginTime;
}
public void setBeginTime(Date beginTime) {
this.beginTime = beginTime;
}
public Date getEndTime() {
return endTime;
}
public void setEndTime(Date endTime) {
this.endTime = endTime;
}
public String getLocation() {
return location;
}
public void setLocation(String location) {
this.location = location;
}
}
TeamMapper.java中添加接口方法
List<Team> queryByVO(QueryTeamVO vo);
TeamMapper.xml添加映射方法
<select id="queryByVO" parameterType="QueryTeamVO" resultMap="baseResultMap">
select * from team
<where>
<!--第一个判断条件中 and可写可不写-->
<if test="name!=null">
and teamName like CONCAT('%',#{name},'%')
</if>
<if test="beginTime!=null">
and createTime>= #{beginTime}
</if>
<if test="endTime!=null">
and createTime <= #{endTime}
</if>
<if test="location!=null">
and location = #{location}
</if>
</where>
</select>
添加测试类:
public class DynamicSqlTest {
private TeamMapper mapper = MybatisUtil.getSqlSession().getMapper(TeamMapper.class);
@Test
public void test1() {
QueryTeamVO vo=new QueryTeamVO();
vo.setName("士");
vo.setEndTime(new Date());
List<Team> teams = mapper.queryByVO(vo);
teams.forEach(team -> {
System.out.println(team);
});
}
}
测试结果
查询sql的条件中与传入参数对应
1.2、set标签
添加Mapper接口方法:
Integer update1(Team team);
添加xml映射:
<update id="update1" parameterType="team">
update team
<set>
<if test="teamName!=null">
teamName=#{teamName},
</if>
<if test="location!=null">
location=#{location},
</if>
<if test="createTime!=null">
createTime=#{createTime}
</if>
</set>
where teamId=#{teamId}
</update>
添加测试方法:
@Test
public void test2(){
Team team = mapper.queryById(1117);
team.setTeamName("hotFire");
team.setCreateTime(new Date());
team.setLocation(null);
Integer num = mapper.update1(team);
System.out.println("影响结果数量:"+num);
}
1.3、forEach标签
1.3.1、批量添加
接口添加方法:
void addList(List<Team> teamList);
mapper添加映射方法
<insert id="addList" parameterType="arrayList">
insert into team(teamName,location) values
<foreach collection="list" item="t" separator=",">
(#{t.teamName},#{t.location})
</foreach>
</insert>
添加测试方法
@Test
public void test3(){
List<Team> list=new ArrayList<>();
for (int i=0;i<3;i++){
Team team=new Team();
team.setTeamName("jk"+i);
team.setLocation("address"+i);
team.setCreateTime(new Date());
list.add(team);
}
mapper.addList(list);
MybatisUtil.getSqlSession().commit();
}
1.3.2、批量删除
接口添加方法:
void delList(List<Integer> list);
mapper映射方法:
<delete id="delList" parameterType="arrayList">
delete from team where teamId in
<!--collection=要遍历的集合,参数直接写集合类型
item=遍历集合中的每一个元素
separator=遍历集合中每个元素用,分割
open=开始包裹元素,close=结束包裹元素-->
<foreach collection="list" item="id" separator="," open="(" close=")">
#{id}
</foreach>
</delete>
添加测试方法:
@Test
public void test4(){
List<Integer> list=new ArrayList<>();
list.add(1116);
list.add(1117);
mapper.delList(list);
MybatisUtil.getSqlSession().commit();
}
二、分页插件
2.1、添加jar包
<!--分页插件-->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>5.3.0</version>
</dependency>
2.2、添加全局配置
<!-- 引入 pageHelper插件 --> <!--注意这里要写成PageInterceptor, 5.0之前的版本都是写PageHelper, 5.0之后要换成PageInterceptor-->
<plugins>
<plugin interceptor="com.github.pagehelper.PageInterceptor">
<!--reasonable:分页合理化参数,默认值为false,直接根据参数进行查询。 当该参数设置为 true 时,pageNum<=0 时会查询第一页,
pageNum>pages(超过总数时),会查询最后一页。 方言可以省略,会根据连接数据的参数url自动推断-->
<!--<property name="reasonable" value="true"/>-->
</plugin>
</plugins>
2.3、添加测试方法
@Test
public void test5(){
// PageHelper.startPage 必须紧邻查询语句,而且只对第一条查询语句生效
PageHelper.startPage(2,5);
// 查询语句结尾不能有;
List<Team> teams = mapper.queryAll();
teams.forEach(team -> {
System.out.println(team);
});
PageInfo<Team> pageInfo=new PageInfo<>(teams);
System.out.println("分页信息如下:");
System.out.println("当前页数:"+pageInfo.getPageNum());
System.out.println("总页数:"+pageInfo.getPages());
System.out.println("前一页:"+pageInfo.getPrePage());
System.out.println("后一页:"+pageInfo.getNextPage());
}
三、mybatis缓存
3.1、缓存的作用
缓存是一般的ORM框架都会提供的功能,目的是提高查询效率和减少数据库压力。将经常查询的数据存在缓存中,用户查询数据时不需要再从磁盘上读取,直接从缓存中读取,提高查询效率,解决高并发问题。
3.2、一级缓存
sqlsession缓存,自动开启。在操作数据库时需要构造sqlsession对象,该对象拥有一个数据结构HashMap用户缓存数据。不同的sqlSession之间的HashMap互不影响。
一级缓存的作用域是同一个sqlSession,在同一个sqlSession执行两次的sql语句,第一次执行完毕就会将查询的结果写入到缓存中,第二次从缓存中读取而不是从数据库中查询,提高查询效率。
当一个sqlSession结束后,sqlsession中的一级缓存也就不存在了。
Mybatis默认开启一级缓存,存在内存中不能被关闭,可以调用clearCache()来清空本地缓存,或者改变缓存的作用域。
3.2.1、一级缓存分析
工作原理
测试类:
public class TestCache {
private SqlSession sqlSession= MybatisUtil.getSqlSession();
@Test
public void test1(){
TeamMapper teamMapper = sqlSession.getMapper(TeamMapper.class);
Team team = teamMapper.queryById(1001);
System.out.println(team);
Team team1 = teamMapper.queryById(1001);
System.out.println(team1);
MybatisUtil.closeSqlSession();//关闭连接,清空缓存
sqlSession= MybatisUtil.getSqlSession();
teamMapper=sqlSession.getMapper(TeamMapper.class);//再次获取连接,此时缓存为空
Team team3 = teamMapper.queryById(1001);
System.out.println(team3);
teamMapper.delete(1131);
MybatisUtil.getSqlSession().commit();//提交之后缓存清空
Team team4 = teamMapper.queryById(1001);
System.out.println(team4);
}
}
清空缓存方式:
- session.clearCache();
- execute update();
- session.close();
- xml配置 flushCache=true
- rollback;
- commit;
3.2、二级缓存
Mapper级别的缓存。多个SqlSession共同去操作一个Mapper的sql语句,多个SqlSession可以共用二级缓存。
二级缓存是多个SqlSession共享的,其作用域是mapper的同一个namespace。
不同的sqlSession两次执行相同的namespace下的sql语句参数相同即执行相同的sql语句,第一次执行会将执行结果写入缓存,第二次执行直接从内存中获取结果,提高查询效率。
Mybatis默认没有开启二级缓存,需要在setting全局设置中配置开启二级缓存。
二级缓存原理图:
3.2.1、启用二级缓存步骤
二级缓存是mapper级别,默认不启用。
1、Mybatis的全局配置文件中开启二级缓存
<settings>
<!-- 是否开启二级缓存 -->
<setting name="cacheEnabled" value="true"/>
</settings>
2、在需要二级缓存的mapper中添加缓存标志
<mapper namespace="com.jsonliu.test.mapper.TeamMapper">
<cache></cache>
...
</mapper>
3、实体类必须实现Serializable接口
public class Team implements Serializable {
...
}
4、测试二级缓存
如果两个Session不是同一个Factory获取,那么二级缓存不起作用。
@Test
public void test2(){
SqlSession sqlSession1 = MybatisUtil.getSqlSession();
TeamMapper mapper1 = sqlSession1.getMapper(TeamMapper.class);
Team team1 = mapper1.queryById(1001);
System.out.println(team1);
MybatisUtil.closeSqlSession();
SqlSession sqlSession2 = MybatisUtil.getSqlSession();
TeamMapper mapper2 = sqlSession2.getMapper(TeamMapper.class);
Team team2 = mapper2.queryById(1001);
System.out.println(team2);
MybatisUtil.closeSqlSession();
SqlSession sqlSession3= MybatisUtil.getSqlSession();
TeamMapper mapper3 = sqlSession3.getMapper(TeamMapper.class);
Integer delete = mapper3.delete(1031);
System.out.println(delete);
MybatisUtil.closeSqlSession();
SqlSession sqlSession4 = MybatisUtil.getSqlSession();
TeamMapper mapper4 = sqlSession4.getMapper(TeamMapper.class);
Team team4 = mapper4.queryById(1001);
System.out.println(team4);
MybatisUtil.closeSqlSession();
}
3.2.2、禁用二级缓存
对于变化比较频繁的sql,可以禁用二级缓存。
在开始了二级缓存的XML中对应的statement中设置useCache=false禁用当前Select语句的二级缓存,意味着该SQL语句每次只需都去查询数据库,不会查询缓存。
useCache默认值是true。对于一些很重要的数据尽不放在二级缓存中。
3.2.3、缓存的属性配置
<cache>
<property name="eviction" value="LRU"/><!--回收策略为LRU-->
<property name="flushInterval" value="60000"/><!--自动刷新时间间隔为60S-->
<property name="size" value="1024"/><!--最多缓存1024个引用对象-->
<property name="readOnly" value="true"/><!--只读-->
</cache>