Java学习笔记-Day76 MyBatis 框架(三)
一、类型别名
类型别名可为 Java 类型设置一个缩写名字。 它仅用于 XML 配置,意在降低冗余的全限定类名书写。要将<typeAliases>
放在mybatis配置文件的<configuration>
中。在配置后,Goods 可以用来代替在任何使用 com.etc.entity.Goods 的地方。
<typeAliases>
<typeAlias type="com.etc.entity.Goods" alias="Goods"/>
<typeAlias type="com.etc.entity.GoodsType" alias="GoodsType"/>
</typeAliases>
二、MyBatis中的 # 和 $ 区别
元素 | # | $ |
---|---|---|
类型匹配 | # :会进行预编译,而且进行类型匹配 |
$ :不进行数据类型匹配 |
替换或者拼接 | # :用于变量替换 |
$ :实质上是字符串拼接 |
场景 | 变量的传递,必须使用# ,使用#{} 就等于使用了PrepareStatement这种占位符的形式,提高效率。可以防止sql注入等等问题。# 方式一般用于传入添加,修改的值或查询,删除的where条件 id值 |
$ 只是只是简单的字符串拼接,要特别小心sql注入问题,对应非变量部分,只能用 $ 。$ 方式一般用于传入数据库对象,比如这种group by 字段 ,order by 字段,表名,字段名等没法使用占位符的就需要使用${} |
三、MyBatis的缓存
MyBatis 内置了一个强大的事务性查询缓存机制,它可以非常方便地配置和定制。 默认情况下,只启用了本地的会话缓存,它仅仅对一个会话中的数据进行缓存。 要启用全局的二级缓存,只需要在你的 SQL 映射文件中添加一行<cache>
。
1、一级缓存
一级缓存(本地缓存)是Session级别的缓存,是默认开启的。一个session做了一个查询操作,它会把这个查询操作的结果放在一级缓存中,如果短时间内这个session又做了同一个查询操作,那么会直接从一级缓存中获取,而不会再去数据库中获取数据。必须是同一个session范围内的操作,才能获取一级缓存的数据。
以下是一级缓存的两种情况:
- 情况1:同一个session,同一个Mapper。
- 情况2:同一个session,不同的Mapper。
package com.etc.test;
import java.io.IOException;
import java.io.InputStream;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import com.etc.dao.GoodsMapper;
import com.etc.entity.Goods;
public class TestGoodsSelectCache {
public static void main(String[] args) throws IOException {
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession session = sqlSessionFactory.openSession();
GoodsMapper mapper = session.getMapper(GoodsMapper.class);
Goods goods = mapper.selectGoodsById(1);
// 一级缓存
System.out.println("*********一级缓存(同一个session,同一个mapper)***********");
Goods goods1 = mapper.selectGoodsById(1);
System.out.println(goods);
System.out.println(goods1);
System.out.println("*********一级缓存(同一个session,不同mapper)***********");
// 一级缓存
GoodsMapper mapper2 = session.getMapper(GoodsMapper.class);
Goods goods2 = mapper2.selectGoodsById(1);
System.out.println(goods2);
}
}
2、二级缓存
不同session范围内的操作才可以获取二级缓存的数据。二级缓存默认不开启。
启用二级缓存的步骤:
(1)在映射文件中添加一行 <cache/>
启用全局的二级缓存。
<cache/>
语句的效果如下:
- 映射语句文件中的所有 select 语句的结果将会被缓存。
- 映射语句文件中的所有 insert、update 和 delete 语句会刷新缓存。
- 缓存会使用最近最少使用算法(LRU, Least Recently Used)算法来清除不需要的缓存。
- 缓存不会定时进行刷新(也就是说,没有刷新间隔)。
- 缓存会保存列表或对象(无论查询方法返回哪种)的 1024 个引用。
- 缓存会被视为读/写缓存,这意味着获取到的对象并不是共享的,可以安全地被调用者修改,而不干扰其他调用者或线程所做的潜在修改。
<?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.etc.dao.GoodsMapper">
<resultMap id="GoodsResultMap" type="Goods">
<id column="goodsid" property="goodsid" />
<result column="goodsname" property="goodsname" />
<result column="goodsprice" property="goodsprice" />
<result column="goodsinfo" property="goodsinfo" />
<result column="goodscount" property="goodscount" />
<result column="cover" property="cover" />
<result column="typeid" property="typeid" />
<result column="shopid" property="shopid" />
<result column="goodsstate" property="goodsstate" />
<!-- 关联一个GoodsType对象 -->
<association property="goodstype" column="typeid" javaType="GoodsType">
<id column="typeid" property="typeid" />
<result column="typename" property="typename" />
<result column="typeinfo" property="typeinfo" />
</association>
</resultMap>
<select id="selectGoodsById" resultMap="GoodsResultMap">
select * from tbl_goods
inner join tbl_goodstype on tbl_goods.typeid=tbl_goodstype.typeid
where tbl_goods.goodsid=#{
goodsid}
</select>
<cache></cache>
</mapper>
(2)实体类实现序列化接口。
package com.etc.entity;
import java.io.Serializable;
public class Goods implements Serializable {
private int goodsid;
private String goodsname;
private Double goodsprice;
private String goodsinfo;
private int goodscount;
private String cover;
private int typeid;
private int shopid;
private int goodsstate;
private GoodsType goodstype;
public Goods(int goodsid, String goodsname, Double goodsprice, String goodsinfo, int goodscount,
String cover, int typeid, int shopid, int goodsstate, Goods goods) {
super();
this.goodsid = goodsid;
this.goodsname = goodsname;
this.goodsprice = goodsprice;
this.goodsinfo = goodsinfo;
this.goodscount = goodscount;
this.cover = cover;
this.typeid = typeid;
this.shopid = shopid;
this.goodsstate = goodsstate;
}
public Goods() {
super();
}
public GoodsType getGoodstype() {
return goodstype;
}
public void setGoodstype(GoodsType goodstype) {
this.goodstype = goodstype;
}
public int getGoodsid() {
return goodsid;
}
public void setGoodsid(int goodsid) {
this.goodsid = goodsid;
}
public String getGoodsname() {
return goodsname;
}
public void setGoodsname(String goodsname) {
this.goodsname = goodsname == null ? null : goodsname.trim();
}
public Double getGoodsprice() {
return goodsprice;
}
public void setGoodsprice(Double goodsprice) {
this.goodsprice = goodsprice;
}
public String getGoodsinfo() {
return goodsinfo;
}
public void setGoodsinfo(String goodsinfo) {
this.goodsinfo = goodsinfo == null ? null : goodsinfo.trim();
}
public int getGoodscount() {
return goodscount;
}
public void setGoodscount(int goodscount) {
this.goodscount = goodscount;
}
public String getCover() {
return cover;
}
public void setCover(String cover) {
this.cover = cover == null ? null : cover.trim();
}
public int getTypeid() {
return typeid;
}
public void setTypeid(int typeid) {
this.typeid = typeid;
}
public int getShopid() {
return shopid;
}
public void setShopid(int shopid) {
this.shopid = shopid;
}
public int getGoodsstate() {
return goodsstate;
}
public void setGoodsstate(int goodsstate) {
this.goodsstate = goodsstate;
}
@Override
public String toString() {
return "Goods [goodsid=" + goodsid + ", goodsname=" + goodsname + ", goodsprice=" + goodsprice + ", goodsinfo="
+ goodsinfo + ", goodscount=" + goodscount + ", cover=" + cover + ", typeid=" + typeid + ", shopid="
+ shopid + ", goodsstate=" + goodsstate + ", goodstype=" + goodstype + "]";
}
}
(3)使用 session.commit();
提交第一个session。
package com.etc.test;
import java.io.IOException;
import java.io.InputStream;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import com.etc.dao.GoodsMapper;
import com.etc.entity.Goods;
public class TestGoodsSelectCache {
public static void main(String[] args) throws IOException {
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession session = sqlSessionFactory.openSession();
GoodsMapper mapper = session.getMapper(GoodsMapper.class);
Goods goods = mapper.selectGoodsById(1);
System.out.println(goods);
session.commit();//让二级缓存生效
// 二级缓存
System.out.println("*********二级缓存(不同的session)***********");
SqlSession session2 = sqlSessionFactory.openSession();
GoodsMapper mapper2 = session2.getMapper(GoodsMapper.class);
Goods goods2 = mapper.selectGoodsById(1);
System.out.println(goods2);
}
}