Mybatis的框架学习总结二
Mybatis的缓存机制
作用:缓存用于提高查询的效率,MyBatis 的缓存是使用 SQL 标签(也就是属性)的 ID 作为缓存的唯一标识的。执行相同的标签可以使用缓存,不同的标签不能使用缓存。
MyBatis 中有两种缓存机制。一级缓冲和二级缓存。
-
一级缓冲默认开启。线程级别的缓存,SqlSession 的缓存, 在一个 SqlSession 生命周期中有效。SqlSession 关闭,缓存清空。
public void find(){ User u = new User(); u.setUname("赵飞燕"); User user = mapper.selBy(u); System.out.println(user); System.out.println("------缓存中的数据-------"); //session.clearCache();//清除SqlSession中的缓存 //默认情况下缓存中有相同的数据,就从缓存中取数据 User u2 = new User(); u2.setUname("赵飞燕"); User user2 = mapper.selBy(u2); System.out.println(user2); } -
二级缓冲, 进程级别的缓存,SqlSessionFactory 的缓存。在一个 SqlSessionFactory 生命周期中有效,可以在多个 SqlSession 生命中期中共享。默认关闭, 需要使用的时候, 要为某个命名空间开启二级缓存(在 mapper.xml 中配置
)。在applicationContext-dao.xml核心配置文件中加。在mapper.xml映射文件中第一行加 。
<!--告知 MyBatis 框架开启二级缓存,在核心文件中添加--> <settings> <setting name="cacheEnabled" value="true"/> </settings>//还需要在 Mapper 对应的xml中添加 cache 标签,表示对哪个mapper 开启缓存。
public void find(){
User u = new User();
u.setUname("赵飞燕");
User user = mapper.selBy(u);
System.out.println(user);
System.out.println("------缓存中的数据-------");
//二级缓存开启之后,会把一级缓存的数据移到SqlSessionFactory中
User u2 = new User();
u2.setUname("赵飞燕");
User user2 = mapper.selBy(u2);
System.out.println(user2);
}
想完整了解的Mybatis底层缓存机制的,可以看看这位大佬的博客。
如何解决数据库中的列名与Pojo类中属性不一致
在查询语句中使用resultType属性,意味着使用Mybatis的Auto-Mapping(自动映射机制),即相同的列名和属性名会自动匹配。因此,当数据库表的列名和类的属性名不一致时,会导致查不到数据。解决该问题可以有两种方式:
- 方法一:查询时,可以通过列别名的方式将列名和属性名保持一致,继续使用自动映射, 从而解决该问题。但是较为麻烦。
- 方法二:使用
, 用于自定义映射关系,可以由程序员自主制定列名和属性名的映射关系。一旦使用 resultMap, 表示不再采用自动映射机制。
<resultMap id="map" type="com.batis.pojo.Tuser">
<id column="sid" property="tid"></id> <!--主键用id标签,用result也可以,只是为了区别主键-->
<!--column写数据库中的列名,property写pojo中对应的属性名-->
<result column="uname" property="tname"></result>
<result column="pwd" property="tpwd"></result>
<result column="spower" property="tpower"></result>
</resultMap>
<select id="find" resultType="map">
select sid,uname,pwd,spower from t_user2
</select>
多表连接查询
业务装配实现多表查询(多对一)
mapper 层只做单表查询操作, 在 service 层进行手动装配,实现关联查询的结果。
实例:
oracle数据库:
create table student(
sid number(3) primary key,
sname varchar2(20),
age number(3),
cid number(3),
constraints fk_student_cid foreign key(cid) references clazz(cid)
)
create table clazz(
cid number(3) primary key,
cname varchar2(20),
roon varchar2(20)
)
创建实体类:创建班级类(Clazz)和学生类(Student),并在 Student 中添加一个 Clazz 类型的属性,用于表示学生的班级信息。
mapper层,提供 StudentMapper 和 ClazzMapper, StudentMapper 查询所有学生信息, ClazzMapper 根据编号查询班级信息。调用 mapper 层,先查询所有学生,再根据每个学生的班级编号查询班级信息, 手动进行组装,称之为业务装配。
resultMap的N+1方式实现多表查询(多对一)
这种方法是在配置文件中直接完成装配,实体类没有变动。
mapper层,提供 StudentMapper 和 ClazzMapper, StudentMapper 查询所有学生信息 , ClazzMapper 根据编号查询班级信息 ,再 StudentMapper 中使用
用于关联一个对象 - property: 指定要关联的属性名。
- select: 设定要继续引用的查询, namespace+id。
- column: 查询时需要传递的列。
<resultMap id="m" type="Student">
<!--同名列的id和result可以省略不写-->
<id property="sid" column="sid"></id>
<result property="" column=""></result> <!--如果pojo实体类中的属性名和数据库中的列名不一致,那么要写result标签中的映射关系-->
<!--property:写在student实体类中持有Clazz的属性名
select:通过哪条sql完成班级的查询,
column:根据指定查询的列名
javaType:查询之后的结果需要封装成的对象
-->
<association property="clazz" select="com.batis.mapper.ClazzMapper.selByCno" javaType="Clazz" column="cid">
<!--同名列的id和result可以省略不写-->
<id></id>
<result></result>
</association>
</resultMap>
<select id="selByName2" resultMap="m">
select * from student where sname = #{0}
</select>
由于装配已经完成,service 层只需要调用 mapper 即可,不需要再进行装配了。
resultMap 的关联方式实现多表查询(多对一)
-
在 StudentMapper.xml 中定义多表连接查询 SQL 语句。一次性查到需要的所有数据,包括对应班级的信息。
-
通过
定义映射关系,并通过 指定对象属性的映射关系。可以把 看成一个 使用。javaType 属性表示当前对象, 可以写全限定路径或别名。
<resultMap id="m" type="Student">
<!--主键得写上,同名列的result可以省略不写-->
<id property="sid" column="sid"></id>
<result property="" column=""></result> <!--如果pojo实体类中的属性名和数据库中的列名不一致,那么要写result标签中的映射关系-->
<!--property:写在student实体类中持有Clazz的属性名
select:通过哪条sql完成班级的查询,
column:根据指定查询的列名
javaType:查询之后的结果需要封装成的对象
-->
<result property="cid" column="cid"></result> <!--外键的列映射关系一定得写上,否则cid没有值-->
<association property="clazz" select="com.batis.mapper.ClazzMapper.selByCno" javaType="Clazz" column="cid">
<id></id>
<result></result>
</association>
</resultMap>
<select id="selByName2" resultMap="m">
select * from student where sname = #{0}
</select>
resultMap 的 N+1 方式实现多表查询(一对多)
mapper层提供 ClazzMapper 和 StudentMapper, ClazzMapper 查询所有班级信息,StudentMapper 根据班级编号查询学生信息 。在 ClazzMapper 中使用
用于关联一个集合
-
property: 指定要关联的属性名
-
select: 设定要继续引用的查询, namespace+id
-
column: 查询时需要传递的列
<!--<collection property="" select="" column=""></collection>-->
<resultMap id="cc" type="Clazz">
<id property="cid" column="cid"></id> <!--作为主键又是外键的列一定得写上,否则clazz中的cid没有值-->
<collection property="stus" select="com.batis.mapper.StudentMapper.selByCid" column="cid"></collection>
</resultMap>
<select id="selByCno" resultMap="cc">
select * from clazz where cid = #{0}
</select>
resultMap 的关联方式实现多表查询(一对多)
-
在 ClazzMapper.xml 中定义多表连接查询 SQL 语句,一次性查到需要的所有数据, 包括对应学生的信息。
-
通过
定义映射关系,并通过 指定集合属性泛型的映射关系。可以把 看成一个 使用。ofType 属性表示集合的泛型,可以写全限定路径或别名。<collection property="" javaType="" ofType="" >
<resultMap id="dd" type="Clazz">
<!--数据库列名与pojo实体类是映射关系一定要写上-->
<id property="cid" column="cid"></id>
<result property="cname" column="cname"></result>
<result property="roon" column="roon"></result>
<!--
javaType:返回的对象类型,查MyBatis的中文文档集合List对象的别名是list
ofType:返回集合的泛型
-->
<collection property="stus" javaType="list" ofType="Student">
<!--数据库列名与pojo实体类是映射关系一定要写上-->
<id property="sid" column="sid"></id>
<result property="sname" column="sname"></result>
<result property="age" column="age"></result>
</collection>
</resultMap>
<select id="selByCno2" resultMap="dd">
select c.cid,c.cname,c.roon,s.sid,s.sname,s.age from clazz c join student s on c.cid = s.cid where c.cid = #{0}
</select>
通过 Auto-Mapping 实现多表查询
a) 通过 MyBatis 的 Auto-Mapping 机制及数据库查询时的别名结合,可以方便的实现多表查询。
b) SQL 语句中, 别名出现特殊符号时,必须进行处理. MySQL可以使用(``)符号,Oracle 可以使用("")符号。缺点:适合于一对多的查询,多对一查集合不好用。
<!--查询:员工的信息及其部门信息(一对多)-->
<?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.batis.mapper.StudentMapper">
<select id="selAuto" resultType="Student">
<!--clazz是Student的实体类中持有Clazz类的实姓名-->
select s.sid,s.sname,s.age,s.cid,c.cid "clazz.cid",c.cname "clazz.cname",c.roon "clazz.roon" from student s join clazz c on s.cid = c.cid where s.sname=#{0}
</select>
</mapper>
用注解完成增删改查
在接口的抽象方法上写@select(“sql语句”),@insert(“sql语句”),@delete(“sql语句”),@update(“sql语句”)以替代mapper.xml文件。
import com.batis.pojo.Student;
import com.batis.pojo.User;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update;
public interface StudentMapper {
@Select(value = "select * from Student where sname=#{0}") //用注解替代了StudentMapper.xml配置文件
public Student selByName(String sname);
@Update(value = "update Student set sname=#{sname},age=#{age} where sid = #{sid} ")
public int updateStu(Student stu);
}

浙公网安备 33010602011771号