Mybatis
1.Mybatis介绍
官网地址: https://mybatis.org/mybatis-3/zh/index.html
MyBatis 是一款优秀的持久层框架,它支持自定义 SQL、存储过程以及高级映射。
MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。
MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。
MyBatis 本是apache的一个开源项目iBatis.
2.特点
- 简单易学:本身就很小且简单。没有任何第三方依赖,最简单安装只要两个jar文件+配置几个sql映射文件易于学习,易于使用,通过文档和源代码,可以比较完全的掌握它的设计思路和实现。
- 灵活:mybatis不会对应用程序或者数据库的现有设计强加任何影响。
- sql写在xml里,便于统一管理和优化。通过sql语句可以满足操作数据库的所有需求。
- 解除sql与程序代码的耦合:通过提供DAO层,将业务逻辑和数据访问逻辑分离,使系统的设计更清晰,更易维护,更易单元测试。sql和代码的分离,提高了可维护性。
- 提供映射标签,支持对象与数据库的orm字段关系映射 提供对象关系映射标签,支持对象关系组建维护 提供xml标签,支持编写动态sql。
3.Mybatis入门案例
1.准备数据库
2.导入jar包
<!--mybatis依赖包-->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.2.0</version>
</dependency>
<!--jdbc依赖包-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!--lombok依赖包-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
3.数据映射
持久层:POJO对象 数据库表
1.数据表:用户的数据信息,持久化到本地磁盘
2.POJO:程序通过对象封装数据信息
映射关系: 一个POJO对象要求映射一张数据表
1.对象名称 映射数据表表名
2.对象的属性 映射数据表中的字段
Mybatis方法定义四类:
List findall(); 返回多个值
User findAll2(); 返回一个值
int update(): 影响的行数
void update2(); 无返回值
编辑POJO对象:
4.编辑mybatis-config.xml配置
文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<!--核心配置文件-->
<configuration>
<!--环境配置标签-->
<environments default="development">
<!--编辑开发环境-->
<environment id="development">
<!--Mybatis采用jdbc的事务控制-->
<transactionManager type="JDBC"/>
<!--jdbc链接最好池化!!!!-->
<dataSource type="POOLED">
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://127.0.0.1:3306/jt?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf8&autoReconnect=true&allowMultiQueries=true"/>
<!--用户名-->
<property name="username" value="root"/>
<!--密码-->
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>
<!--Mybatis加载Mapper映射文件-->
<mappers>
<mapper resource="mybatis/mappers/UserMapper.xml"/>
</mappers>
</configuration>
5.编辑UserMapper接口
public interface UserMapper {
//指定接口方法 查询demo_user所有数据
List<User> findAll();
}
6.编辑UserMapper.xml的映射
文件
说明:由于mybatis需要操作数据库,编辑Sql语句,采用xml映射文件维护Sql语句
**关系
:
1.一个接口
对应一个xml的映射文件
2.一个接口方法
对应一个映射文件的Sql
namespace与接口对应,id表示接口方法,resultType返回值POJO对象的类型
<?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">
<!--1.namespace是mybaits映射文件的唯一标识,与接口对应-->
<mapper namespace="com.jt.mapper.UserMapper">
<!--2.执行业务操作
id 表示接口方法
resultType 返回值的POJO对象类型User
-->
<select id="findAll" resultType="com.jt.pojo.User">
select * from demo_user
</select>
<!-- <insert></insert>-->
<!-- <update></update>-->
<!-- <delete></delete>-->
</mapper>
7.Mabatis加载mapper映射文件
3.Mybatis入门案例2
1.编辑TestMybatis
每个基于 MyBatis 的应用都是以一个 SqlSessionFactory 的实例为核心的。SqlSessionFactory 的实例可以通过 SqlSessionFactoryBuilder 获得。而 SqlSessionFactoryBuilder 则可以从 XML 配置文件或一个预先配置的 Configuration 实例来构建出 SqlSessionFactory 实例
public class TestMybatis {
/**
* 规则说明:
* 1.创建SqlSessionFactory 工厂模式
* */
public void demo1() throws IOException {
//1.1指定配置文件的根目录
String resource = "mybatis-config.xml";
//1.2通过I/O流 加载配置文件 org.apache.ibatis.io.Resources包路径
InputStream inputStream = Resources.getResourceAsStream(resource);
//1.3实例化工厂对象
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
}
}
2.从SqlSessionFactory中获取SqlSession 数据库链接 + 传输器对象
既然有了 SqlSessionFactory,顾名思义,我们可以从中获得 SqlSession 的实例。SqlSession 提供了在数据库执行 SQL 命令所需的所有方法。你可以通过 SqlSession 实例来直接执行已映射的 SQL 语句。
//2.1获取SqlSession 通过SqlSession可以直接操作数据库
SqlSession sqlSession = sqlSessionFactory.openSession();
//2.2获取接口对象
UserMapper usermapper = sqlSession.getMapper(UserMapper.class);
3.执行业务调用
package com.jt;
import com.jt.mapper.UserMapper;
import com.jt.pojo.User;
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 org.junit.Test;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
public class TestMybatis {
/**
* 规则说明:
* 1.创建SqlSessionFactory 工厂模式
* 2.获取SqlSession 数据库链接 + 传输器对象
* 3.获取Mapper接口对象
* 4.完成业务调用
* 5.关闭链接
* */
@Test
public void demo1() throws IOException {
//1.1指定配置文件的根目录
String resource = "mybatis-config.xml";
//1.2通过I/O流 加载配置文件 org.apache.ibatis.io.Resources包路径
InputStream inputStream = Resources.getResourceAsStream(resource);
//1.3实例化工厂对象
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//2获取SqlSession 通过SqlSession可以直接操作数据库
SqlSession sqlSession = sqlSessionFactory.openSession();
//3获取接口对象
UserMapper usermapper = sqlSession.getMapper(UserMapper.class);
//4.调用接口方法
List<User> userList = usermapper.findAll();
System.out.println(userList);
//5.暂时手动关闭链接
sqlSession.close();
}
}
4.Mybatis常见错误
1.jar包添加错误
2.配置文件名称不一致
3.数据源配置异常
数据库版本要求:MySQL5.5以上版本 mariaDB10 以上
驱动异常:
4.映射文件加载错误
5.接口与映射文件不匹配
4.Mybatis配置
1.添加jar包,复制src文件夹
2.修改yml配置文件application.yml
3.关于主启动类异常说明
开箱即用规则
报错原理:由于Mybatis依赖了JDBC的jar包.,但是该jar包文件是启动项.,当主启动类运行时,开始加载主启动项。 但是JDBC需要链接数据库,所以必须有相关的配置信息.但是此时YML文件中没有数据源的配置,所以报错。
4.配置yml文件
yml 文件 0 不解析 如果字母以0开题则引号包裹
配置application.yml文件:配置端口号、配置数据源、配置映射文件
#1.配置端口号 注意空格
server:
port: 8090
servlet:
context-path: /
#2.配置数据源
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/jt?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf8&autoReconnect=true&allowMultiQueries=true
username: root
password: 123456
#3.配置映射文件
mybatis:
type-aliases-package: com.jt.pojo
#将所有的映射文件全部加载
mapper-locations: classpath:/mappers/*.xml
#开启驼峰映射
configuration:
map-underscore-to-camel-case: true
5.Mapper/Dao 持久层用 @Mapper注解
将Mapper接口交给Spring容器管理
package com.jt.mapper;
import com.jt.pojo.User;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
@Mapper //将接口交给Spring容器管理Map<userMapper,JDK代理对象>
public interface UserMapper {
//指定接口方法 查询demo_user所有数据
List<User> findAll();
}
6.编辑测试类
package com.jt;
import com.jt.mapper.UserMapper;
import com.jt.pojo.User;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.List;
@SpringBootTest
class MybatisDemo1ApplicationTests {
@Autowired
private UserMapper userMapper;
@Test
public void testDemo1(){
List<User> userList = userMapper.findAll();
System.out.println(userList);
}
}
5.Mybatis基本用法
1.常见CURD操作,根据id查询
1.编辑接口类
package com.jt.mapper;
import com.jt.pojo.User;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
@Mapper
public interface UserMapper {
List<User> findAll();
//根据id查询数据库
User findUserById(int id);
}
2.编辑测试类
@Test
public void testFindUserById(){
int id = 1;
userMapper.findUserById(id);
}
3.编辑映射文件UserMapper.xml
resultType 返回值的类型,封装为对象
<!--根据id查询数据库
动态取值:#{key}
-->
<select id="findUserById" resultType="com.jt.pojo.User">
select * from demo_user where id = #{id}
</select>
2.SQL语句打印
编辑yml文件
#4.打印sql com.jt.mapper 下的sql日志
logging:
level:
com.jt.mapper:debug
3.常见CURD操作,根据name、age查询
1.编辑接口类
package com.jt.mapper;
import com.jt.pojo.User;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
@Mapper //将接口交给Spring容器管理Map<userMapper,JDK代理对象>
public interface UserMapper {
//指定接口方法 查询demo_user所有数据
List<User> findAll();
//根据id查询数据库
User findUserById(int id);
List<User> findUserByNA(User user);
}
2.编辑测试类
/**
* 知识点:
* 1.如果是多个参数传递,则一般采用对象的方式封装
* */
@Test
public void testFindByNa(){
String name = "孙尚香";
List<User> userList = userMapper.findUserByNA();
System.out.println(userList);
}
3.编辑映射文件UserMapper.xml
<!--根据名称和age查询数据
知识点:别名包 在配置文件中指定包路径:可以自动的实现包路径的拼接
resultType规则:
1.首先根据别名包匹配,设定。。
2.如果匹配不成功,则按照路径匹配
参数传递规则:
1.如果是单个参数,则使用#{key} 获取的参数的值
2.如果是对象参数,则使用#{属性} 获取的是属性值
-->
<select id="findUserByNA" resultType="com.jt.pojo.User">
select * from demo_user where name = #{name} and age = #{age}
</select>
</mapper>
4.查询age>18 age<100的用户
如果多个参数不方便使用User对象封装时,应该使用万能的集合Map
如果传递的参数是Map,则使用#{key}
xml转义字符:
1. > >
2. < <
3. & &
万能转义:<![CDATA[xxx]]>
1.编辑UserMapper文件
<select id="findUserByAge" resultType="User">
select * from demo_user where age > #{minAge} and age > #{maxAge}
</select>
2.编辑测试类
/**
* 知识点:
* 如果多个参数不方便使用User对象封装时,应该使用万能的集合Map
*
* */
@Test
public void testFindUserByAge(){
int minAge = 18;
int maxAge = 100;
Map<String,Integer> map = new HashMap();
map.put("minAge", minAge);
map.put("maxAge", maxAge);
List<User> userList = userMapper.findUserByAge(map);
System.out.println(userList);
}
3.编辑接口类
package com.jt.mapper;
import com.jt.pojo.User;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
import java.util.Map;
@Mapper //将接口交给Spring容器管理Map<userMapper,JDK代理对象>
public interface UserMapper {
//指定接口方法 查询demo_user所有数据
List<User> findAll();
//根据id查询数据库
User findUserById(int id);
List<User> findUserByNA(User user);
List<User> findUserByAge(Map<String, Integer> map);
}
5.利用注解@Param将Map封装
mybatis只支持单值传参 将多值封装为单值
@Param将数据封装为Map集合
@Param(“key”) int minAge(值)
1.编辑测试类
/**
* 知识点:
* 利用注解实现数据的封装,封装Map集合
* */
@Test
public void testFindUserByAge2(){
int minAge = 18;
int maxAge = 100;
List<User> userList = userMapper.findUserByAge2(minAge,maxAge);
System.out.println(userList);
}
2.编辑接口类
//mybatis只支持单值传参 将多值封装为单值
//注解:@Param
List<User> findUserByAge2(@Param("minAge") int minAge, @Param("maxAge") int maxAge);
3.编辑映射文件
<select id="findUserByAge2" resultType="User">
<![CDATA[
select * from demo_user where age > #{minAge} and age < #{maxAge}
]]>
</select>
6.模糊查询
1.业务需求
查询name字段中包含“君”的用户
2.编辑测试方法
@Test
public void testFindUserByLike(){
//String name = "%"+"君"+"%";
String name = "君";
List<User> userList = userMapper.findUserByLike(name);
System.out.println(userList);
}
3.编辑接口类
List<User> findUserByLike(String name);
4.编辑映射文件
<!--windows系统:数据库不区分大小写
linux系统: 区分大小写
-->
<select id="findUserByLike" resultType="User">
select * from demo_user where name like "%"#{name}"%"
</select>
5.like与concat一起用防止sql注入
7.Sql标签用法
1.业务需求
说明:Sql语句中经常出现重复的数据,如果每次重复的内容都自己手写,开发效率低
用法:Sql标签
优化:将公共的Sql进行抽取
优势:Sql标签可以
2.Sql标签
<!--Sql标签:抽取公共的Sql语句-->
<sql id="tableColumn">
id,name,age,sex
</sql>
<select id="findUserByLike" resultType="User">
select <include refid="tableColumn"/> from demo_user where name like "%"#{name}"%"
</select>
8.Mybatis中的集合参数写法
1.业务需求
查询id=1,2,3,5,7的数据
2.编辑测试方法
@Test
public void testFindListByIn(){
int[] array = {1,2,3,5,7};
List<User> userList = userMapper.findListByIn(array);
System.out.println(userList);
}
3.编辑接口类
List<User> findListByIn(int[] array);
4.编辑映射文件
关于Mybatis的遍历的写法:
foreach标签:
1.collection 需要遍历的集合
1.1数组 关键字:array
1.2list集合 关键字:list
1.3Map<key,array/list> 关键字:key
2.open/close 循环体的开始和结束 可以写到循环之外简化标签
3.item 当前遍历数据的变量 是id
4.separator 分割符
<select id="findListByIn" resultType="User">
select * from demo_user where id in(
<foreach collection="array" item="id" separator=",">
#{id}
</foreach>
)
</select>
6.动态Sql
1.动态Sql-where条件
需求:
根据对象中不为null的数据,充当where条件,进行查询
编辑测试方法:
@Test
public void testDemo1(){
User user = new User();
user.setAge(18).setSex("女"); //动态变化的数据
List<User> userList = userMapper2.findUserList(user);
System.out.println(userList);
}
编辑接口类:
List<User> findUserList(User user);
编辑映射文件:
根据对象中不为空的属性当作where条件
语法:
1.如果判断成立则动态拼接属性 id = #{id}
2.where标签 去除where后边多余的and/or
<!--根据对象中不为空的属性当作where条件
语法:
1.如果判断成立则东态拼接属性 <if test="id != null">#{id}</if>
2.where标签 去除where后边多余的and/or
-->
<select id="findUserList" resultType="User">
select * from demo_user
<where>
<if test="id != null">id=#{id}</if>
<if test="name != null">and name=#{name}</if>
<if test="age != null"> and age=#{age}</if>
<if test="sex != null"> and sex=#{sex}</if>
</where>
</select>
2.动态Sql-set条件
编辑测试方法:
//执行动态的更新操作
//根据对中不为null的元素,充当set条件
@Test
public void testDemo2(){
User user = new User();
user.setId(235).setName("王二麻子").setAge(25).setSex("男");
userMapper2.updateUser(user);
System.out.println("更新成功");
}
编辑接口类:
void updateUser(User user);
编辑映射文件:
<update id="updateUser">
update demo_user
<set>
<if test="name != null">name = #{name},</if>
<if test="age != null">age = #{age},</if>
<if test="sex != null">sex = #{sex}</if>
</set>
where id = #{id}
</update>
3.动态Sql-choose、when、otherwise
如果不想使用所有的条件可以使用choose类似于java中的switch
语法:如果name有值,则按照name查询,否则按照age查询,age无值则按照 sex查询数据
编辑测试方法:
@Test
public void testDemo3(){
User user = new User();
user.setName(null).setAge(18).setSex("女");
List<User> userList = userMapper2.findUserByNS(user);
System.out.println(userList);
}
编辑接口类:
List<User> findUserByNS(User user);
编辑映射文件:
<select id="findUserByNS" resultType="User">
select * from demo_user
<where>
<choose>
<when test="name != null">name =#{name}</when>
<when test="age != null">age =#{age}</when>
<otherwise>sex = #{sex}</otherwise>
</choose>
</where>
</select>
7.resultMap
说明:当表中字段与pojo中的属性名称不一致时
,或者进行多表联查时
,需要使用resultMap的方式进行映射
表中字段名称与对象中属性名称不一致,结果数据不能映射
1.建表:
2.创建pojo Dog类:
@Data
@Accessors(chain = true)
@NoArgsConstructor
@AllArgsConstructor
public class Dog {
private Integer dogId;
private String dogName;
private Integer age;
}
3.关于返回属性的说明
- resultType:只能支持
字段的名称
与属性的名称
一致时,才能自动映射
- resultMap:可以支持任意类型的映射,万能的结构
8.开启驼峰规则映射
说明:在业务中经常出现该现象: 字段user_id 属性userId 属性和字段有驼峰映射规则,但是不采用resultType方式映射,则不能正常赋值。
解决方案:
1.resultMap 繁琐
2开启驼峰映射规则
9.Mybatis关联关系
1.常见关联关系
1.一对一 一个员工对应一个部门
2.一个多 老师对应多个学生/一个部门对应多个员工
3.多对多 一个老师对应多个学生 一个学生对应多个老师(双向的多对多)
2.创建数据表
emp表
dept表
3.关联查询
1.笛卡尔积
特点:只获取两张表的交集
SELECT * FROM emp,dept WHERE emp.dept_id=dept.dept_id
2.连接查询
分类:1左连接(查询左表所有数据) 2内连接 3右连接(查询右表所有数据)
#左连接
SELECT * FROM emp LEFT JOIN dept ON emp.dept_id=dept.dept_id
4.一对一封装
员工对部门
1.如果操作单表 一般使用resultType
2.如果进行关联操作 一般使用resultMap
3.如果是多表关联操作,不允许出现重复字段名
**关于自动映射规则:**
1.没有映射关联时如果属性和字段名相同,则可以省略不写
2.有关联映射,则需要添加自动映射开关autoMapping="true"
,自动开关只对当前对象有效
1.编辑Emp实例类
@Data
@Accessors(chain = true)
@NoArgsConstructor
@AllArgsConstructor
public class Emp implements Serializable {
private Integer id;
private String name;
private Integer age;
//关联关系:一个员工对应一个部门
private Dept dept;
//private Integer deptId;
}
2.编辑测试方法
@Test
public void testOneToOne(){
List<Emp> empList = empMapper.findAll();
System.out.println(empList);
}
3.编辑映射文件
关联另外的表用标签,
<?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">
<!--1.namespace是mybatis映射文件的唯一标识,与接口对应-->
<mapper namespace="com.jt.mapper.EmpMapper">
<!--
规则:
1.如果操作单表 一般使用resultType
2.如果进行关联操作 一般使用resultMap
3.如果是多表关联操作,不允许出现重复字段名
-->
<select id="findAll" resultMap="empRM">
select <include refid="tableColumn"/> from emp,dept where emp.dept_id=dept.dept_id
</select>
<!--
关于自动映射规则:
1.没有映射关联时如果属性和字段名相同,则可以省略不写
2.有关联映射,则需要添加自动映射开关autoMapping="true"
自动开关只对当前对象有效
-->
<resultMap id="empRM" type="Emp" autoMapping="true">
<!--id代表主键-->
<id column="id" property="id"/>
<!--一对一关联封装
知识点:
1.一对一关联association标签
2.必须要指定属性的类型 javaType属性
-->
<association property="dept" javaType="Dept" autoMapping="true">
<!--主键必填-->
<id column="dept_id" property="deptId"></id>
<!--由于开启驼峰规则,下列可以省略-->
<!--<result column="dept_name" property="deptName"/>-->
</association>
</resultMap>
<sql id="tableColumn">
emp.id,emp.name,emp.age,dept.dept_id,dept.dept_name
</sql>
</mapper>
5.一对多封装
部门对员工
1.编辑测试方法
//一对多,一个部门中要求获取多个员工
@Test
public void testOneToMore(){
List<Dept> deptList = deptMapper.findAll();
System.out.println(deptList);
}
2.编辑实例类
@Data
@Accessors(chain = true)
@NoArgsConstructor
@AllArgsConstructor
public class Dept implements Serializable {
private Integer deptId;
private String deptName;
//关联关系:一个部门对应多个员工
private List<Emp> emps;
}
3.编辑映射文件
一对多关联另外表时用标签,
<?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">
<!--1.namespace是mybatis映射文件的唯一标识,与接口对应-->
<mapper namespace="com.jt.mapper.DeptMapper">
<select id="findAll" resultMap="deptRM">
select dept.dept_name,emp.*
from dept,emp
where dept.dept_id = emp.dept_id
</select>
<resultMap id="deptRM" type="Dept" autoMapping="true">
<!--id代表主键-->
<id column="dept_id" property="deptId"/>
<!--一对多封装 collection-->
<collection property="emps" ofType="Emp" autoMapping="true">
<id column="id" property="id"/>
</collection>
</resultMap>
</mapper>
10.Mabatis注解开发
1.编辑测试类
package com.jt;
import com.jt.mapper.DeptMapper;
import com.jt.mapper.EmpMapper;
import com.jt.mapper.UserAnnoMapper;
import com.jt.mapper.UserMapper;
import com.jt.pojo.Dept;
import com.jt.pojo.Emp;
import com.jt.pojo.User;
import org.apache.ibatis.annotations.Select;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
@SpringBootTest
class MybatisDemo1ApplicationTests4 {
@Autowired
private UserAnnoMapper annoMapper;
@Test
//利用注解可以根据返回值类型,自动映射
public void testFindAll(){
List<User> list = annoMapper.findAll();
System.out.println(list);
}
@Test
//利用注解可以根据返回值类型,自动映射
public void testFindAll2(){
int id = 1;
List<User> list = annoMapper.findUserById(id);
System.out.println(list);
}
//根据姓名查询
@Test
public void testFindByNa(){
User user = new User();
user.setName("王六子");
List<User> list = annoMapper.findUserByNa(user);
System.out.println(list);
}
//插入数据
@Test
public void testInsert(){
User user = new User();
user.setName("刘阳").setAge(22).setSex("女");
int rows = annoMapper.insertUser(user);
System.out.println(rows);
}
//修改数据
@Test
public void testSetUser(){
User user = new User();
user.setId(236).setName("刘阳").setAge(21).setSex("女");
int rows = annoMapper.updateUser(user);
System.out.println(rows);
}
//删除数据
@Test
public void testDelete(){
User user = new User();
user.setId(236);
int rows = annoMapper.deleteUser(user);
System.out.println(rows);
}
}
2.编辑接口类
package com.jt.mapper;
import com.jt.pojo.User;
import org.apache.ibatis.annotations.*;
import java.util.List;
//该Mapper主要测试注解开发
@Mapper
@CacheNamespace //使用注解的二级缓存
public interface UserAnnoMapper {
@Select("select * from demo_user")
List<User> findAll();
@Select("select * from demo_user where id = #{id}")
List<User> findUserById(int id);
@Insert("insert into demo_user values(null,#{name},#{age},#{sex})")
int insertUser(User user);
@Update("update demo_user set id= #{id},age = #{age},sex = #{sex} where name = #{name}")
int updateUser(User user);
@Delete("delete from demo_user where id = #{id}")
int deleteUser(User user);
@Select("select * from demo_user where name = #{name}")
List<User> findUserByNa(User user);
List<User> findCache1();
}
11.Mybstis缓存
1.缓存说明
说明: 如果相同的数据需要多次查询,则可以使用缓存的方式处理,提高用户的响应速度。
mybatis中提供了两种缓存机制:
一级缓存: SqlSession级别 在同一个sqlSession内实现数据共享 默认开启
二级缓存:SqlSessionFactory级别 由同一个sqlSessionFactory生产的SqlSession数据共享 默认开启 + 配置
易错项:二级缓存默认开启
3.缓存测试
说明:SpringBoot在使用一二级缓存时,有个别特殊要求注意
3.1一级缓存测试(@Transactional)
现象:采用SpringBoot的方式进行测试时,sql执行多次,一级缓存无效
解决:添加事务的注解,SpringBoot中添加了之后,默认采用一个SqlSession
编辑测试方法:
@Test
@Transactional //添加事务
public void testCache1(){
List<User> userList1 = userMapper.findCache1();
List<User> userList2 = userMapper.findCache1();
List<User> userList3 = userMapper.findCache1();
List<User> userList4 = userMapper.findCache1();
}
3.2二级缓存测试
测试策略:
说明:为了构建多个mapper对象,需要准备多个线程进行测试,可以通过浏览器让用户发起多次请求之后,测试二级缓存是否有效。
层级代码结构:
- Controller 层 SpringMVC 面向接口编程 2:2:1
- Service 层 Spring
- Mapper/Dao层 Mybatis
编辑Mapper层
List<User> findCache1();
编辑service层:
编辑UserService接口类:
package com.jt.service;
import com.jt.pojo.User;
import java.util.List;
public interface UserService {
List<User> findCache1();
List<User> findAll();
}
编辑UserServiceImpl实现类:
package com.jt.service;
import com.jt.mapper.UserAnnoMapper;
import com.jt.pojo.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class UserServiceImpl implements UserService {
@Autowired
private UserAnnoMapper userMapper;
@Override
public List<User> findCache1() {
return userMapper.findCache1();
}
@Override
public List<User> findAll() {
return userMapper.findAll();
}
}
编辑controller类:
package com.jt.controller;
import com.jt.pojo.User;
import com.jt.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController
@ResponseBody
public class UserController {
@Autowired
private UserService userService;
/**
* 要求返回List集合的JSON串
* */
@GetMapping("/findCache")
public List<User> findCache1(){
return userService.findCache1();
}
@GetMapping("/findAll")
public List<User> findAll(){
return userService.findAll();
}
}
3.2.1使用标签开启二级缓存
<?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">
<!--1.namespace是mybatis
s映射文件的唯一标识,与接口对应-->
<mapper namespace="com.jt.mapper.UserAnnoMapper">
<!--
1.让二级缓存在当前Mapper层有效
2.POJO必须序列化
-->
<cache/>
<select id="findCache1" resultType="User">
select * from demo_user
</select>
</mapper>
3.2.1使用二级注解开启二级缓存@CacheNamespace
业务说明: Mybatis中采用注解方式的查询和xml映射文件的查询的方式不一样. 两者不可以混用.
使用注解的二级缓存。
12.传入参数类型
parameterType为传入参数类型,resultType传出参数类型,resultMap当实体类属性名与数据库字段名不相同时使用