目录
1 、mybatis高级用法
1.1 、一对一案例
注意事项:mybatis在实现数据封装时,要求字段名称唯一
/*左连接*/
SELECT * FROM emp
LEFT JOIN
dept
ON emp.dept_id=dept.dept_id
/*普通连接*/
SELECT * FROM emp ,dept
WHERE dept.dept_id =emp.dept_id
/*高效写法:去除重复的数据*/
SELECT e.id,e.name,e.age,d.dept_id,d.dept_name
FROM emp e,dept d
WHERE e.dept_id=d.dept_id
最后查询得到的结果:
EmpMapper.xml
<select id="findAll" resultMap="empRM">
select e.id,e.name,e.age,d.dept_id,d.dept_name
from emp e,dept d
where e.dept_id = d.dept_id
</select>
<!--如果映射的字段和对象的属性一致则可以省略不写
最好保留主键的字段信息
如果需要封装单个对象则使用association标签
property是type里的封装对象的属性
javaType是指定属性的类型,注意里面的路径
如果遇到关联的封装必须全部配置映射关系
如果属性和字段名一致则可以使用autoMapping="true"实现自动映射-->
<resultMap id="empRM" type="Emp" autoMapping="true">
<id column="id" property="id"/>
<!-- <result column="name" property="name"/>-->
<!-- <result column="age" property="age"/>-->
<!-- 完成Dept的封装-->
<association property="dept" javaType="Dept">
<id column="dept_id" property="deptId"/>
<result column="dept_name" property="deptName"/>
</association>
</resultMap>
DeptMapper.xml
<!--
ORM思想: 对象关系映射.
属性: deptId,deptName
字段: dept_id,dept_name
resultType说明:
当结果集中的字段名称,如果与属性的名称一致时,
才会实现自动的数据封装.
resultMap="" 自定义的封装数据的结构
-->
<select id="findAll" resultMap="deptRM">
select * from dept
</select>
<!--自定义映射关系的
语法:
1.id标签代表主键 (每张表中都会有一个主键)
1.1.column: 代表结果集中的字段.
1.2.property: 对象中的属性
2.result 除了主键之外的配置信息
-->
<resultMap id="deptRM" type="Dept">
<id column="dept_id" property="deptId"/>
<result column="dept_name" property="deptName"/>
</resultMap>
TestMybatis.java
/*
一对一:
规定:一个员工对应一个部门
选取方向:员工方
需求:需要在员工中完成部门对象封装
*/
@Test
public void testOneToOne(){
SqlSession sqlSession = sqlSessionFactory.openSession();
EmpMapper empMapper = sqlSession.getMapper(EmpMapper.class);
List<Emp> list=empMapper.findAll();
System.out.println(list);
sqlSession.close();
}
1.2 、关联查询和子查询的说明
关联查询:通过大量的SQL语句实现数据的关联查询,其中SQL语句相对复杂但是数据封装简单。
子查询:可以通过子查询的方式实现复杂的数据封装,其中SQL语句几乎都是单表查询SQL简单。
1.3 、子查询实现一对一封装
@Test
public void testOneToOne2(){
SqlSession sqlSession = sqlSessionFactory.openSession();
EmpMapper empMapper = sqlSession.getMapper(EmpMapper.class);
List<Emp> list=empMapper.findAllWhere();
System.out.println(list);
sqlSession.close();
}
<!-- where条件子查询-->
<select id="findAllWhere" resultMap="empRM2">
select * from emp
</select>
<!-- 子查询的说明:column="子查询的字段信息"
select="" 根据column中的数据实现子查询
-->
<resultMap id="empRM2" type="Emp" autoMapping="true">
<id column="id" property="id"/>
<association property="dept" javaType="Dept"
column="dept_id" select="findDept"/>
</resultMap>
<select id="findDept" resultMap="deptRM">
select * from dept where dept_id = #{dept_id}
</select>
<resultMap id="deptRM" type="Dept">
<id column="dept_id" property="deptId"/>
<result column="dept_name" property="deptName"/>
</resultMap>
1.4 、一对多案例
/* 一对多测试 一个部门下有多个用户信息 */
@Test
public void testOneToMore(){
SqlSession sqlSession = sqlSessionFactory.openSession();
DeptMapper deptMapper = sqlSession.getMapper(DeptMapper.class);
List<Emp> list=deptMapper.findDept();
System.out.println(list);
sqlSession.close();
}
<!-- 一对多 -->
<select id="findDept" resultMap="listRM">
SELECT e.id,e.name,e.age,d.dept_id,d.dept_name
FROM
emp e LEFT JOIN dept d
ON e.dept_id = d.dept_id
</select>
<!--封装-->
<resultMap id="listRM" type="Dept">
<id column="dept_id" property="deptId"/>
<result column="dept_name" property="deptName"/>
<!-- 封装集合说明:
collection:封装集合的固定写法
property:主对象dept的信息 指定属性 名为emps
ofType:什么什么的 封装list集合的泛型对象
-->
<collection property="emps" ofType="Emp" autoMapping="true">
<id column="id" property="id"></id>
</collection>
</resultMap>
1.5 、驼峰规则映射
说明:mybatis在映射时经常出现字段名称与属性名称不一致的现象,其中一部分可以采用驼峰规则的方式完成自动映射。
编辑mybatis-config.xml文件(写在configuration标签下)
<!-- mybatis核心配置-->
<settings>
<!-- 开启驼峰映射规则,dept_id自动映射deptId-->
<setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>
最好留有id的标签 方便以后调用id会用到
<!--封装 驼峰规则开启后 可以简化封装的过程id deptname都可以省略不写
但是又是关联查询有要求必须在autoMapping否则返回不了数据不会报错-->
<resultMap id="listRM" type="Dept" autoMapping="true">
<id column="dept_id" property="deptId"/>
<!-- <result column="dept_name" property="deptName"/>-->
<collection property="emps" ofType="Emp" autoMapping="true">
<id column="id" property="id"></id>
</collection>
</resultMap>
1.6 、Mybatis缓存机制
缓存机制:缓存是用来解决查询数据的问题
说明:引入缓存可以有效降低用户访问物理设备的频次,提高用户响应速度
扩展:
1.Mybatis自身缓存:一级缓存/二级缓存
2.Redis缓存 读取10w次/秒,写8s/一次(没看清后面再改)
一级缓存:Mybatis默认开启一级缓存,一级缓存可以在同一个SqlSession对象中查询相同的数据,可以实现数据的共享(缓存操作)
//mybatis 一级缓存 默认开启 同一个SQLSession对象内部有效
@Test
public void cache1(){
SqlSession sqlSession = sqlSessionFactory.openSession();
DeptMapper deptMapper = sqlSession.getMapper(DeptMapper.class);
List<Dept> list1=deptMapper.findAll();
List<Dept> list2=deptMapper.findAll();
List<Dept> list3=deptMapper.findAll();
System.out.println(list1==list2);
sqlSession.close();
}
//mybatis 一级缓存在不同SQLSession中无效
@Test
public void cache2(){
SqlSession sqlSession = sqlSessionFactory.openSession();
DeptMapper deptMapper = sqlSession.getMapper(DeptMapper.class);
deptMapper.findAll();
SqlSession sqlSession1=sqlSessionFactory.openSession();
DeptMapper deptMapper1=sqlSession1.getMapper(DeptMapper.class);
deptMapper1.findAll();
sqlSession.close();
sqlSession1.close();
}
二级缓存:mybatis中默认是开启的,但是需要手动标识一下,二级缓存可以在同一个SQLSession内部有效。
全局配置:cacheEnabled全局性的开启或关闭所有映射文件中已配置的任何缓存
默认情况下只启动了本地的会话缓存,它仅仅对一个会话的数据进行缓存,要启用全局的二级缓存,只需要在SQL映射文件中添加一行<cache/>代码即可。
/**
* 二级缓存说明:
* sqlSession查询数据之后,会将缓存信息保存到一级缓存中.但是不会立即将
* 缓存交给二级缓存保管.
* 如果需要使用二级缓存,则必须将sqlSession业务逻辑执行成功
* 之后,并且关闭.
*/
@Test
public void cache2(){
SqlSession sqlSession = sqlSessionFactory.openSession();
DeptMapper deptMapper = sqlSession.getMapper(DeptMapper.class);
deptMapper.findAll();
//关闭一级缓存
sqlSession.close();
SqlSession sqlSession1=sqlSessionFactory.openSession();
DeptMapper deptMapper1=sqlSession1.getMapper(DeptMapper.class);
deptMapper1.findAll();
sqlSession1.close();
}