👌 棒棒有言:也许我一直照着别人的方向飞,可是这次,我想要用我的方式飞翔一次!人生,既要淡,又要有味。凡事不必太在意,一切随缘,缘深多聚聚,缘浅随它去。凡事看淡点看开些,顺其自然,无意于得,就无所谓失。人生,看轻看淡多少,痛苦就远离你多少。
👌 本章简介:MyBatis本是apache的一个开源项目iBatis,2010年这个项目由apache software foundation迁移到了google code,并且改名为MyBatis。2013年11月迁移到Github。iBATIS一词来源于“internet”和“abatis”的组合,是一个基于Java的持久层框架。iBATIS提供的持久层框架包括SQL Maps和Data Access Objects(DAOs)。
当前,最新版本是MyBatis 3.5.11,其发布时间是2022年09月18日。
👍 作者:get棒棒给个关注呗
👍非常重要 :
如果不介意麻烦动动你们的小手点个关注
Mybatis框架
MyBatis简介
MyBatis 是一款优秀的持久层框架,它支持自定义 SQL、存储过程以及高级映射。MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录
2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis 。2013年11月迁移到Github。
回顾JDBC的使用步骤:
-
1.加载驱动
Class.forName("com.mysql.jdbc.Driver");
-
2.获取连接对象
DiverManerger.getConnection(url,username,password)
-
3.获取执行sql的Statement对象
connection.CreateStatement();
-
4.执行sql语句
-
5.处理结果集
-
6.释放连接
connection.Close()
与JDBC相比:
-
Mybatis通过参数映射方式,可以将参数灵活的配置在SQL语句中的配置文件中,避免在Java类中配置参数
-
Mybatis通过输出映射机制,将结果集的检索自动映射成相应的Java对象,避免对结果集手工检索
-
Mybatis可以通过Xml配置文件对数据库连接进行管理
MyBatis整体架构及运行流程
Mybatis整体构造由 数据源配置文件、Sql映射文件、会话工厂、会话、执行器和底层封装对象组成
1.数据源配置文件
通过配置的方式将数据库的配置信息从应用程序中独立出来,由独立的模块管理和配置。Mybatis的数据源配置文件包含数据库驱动、数据库连接地址、用户名密码、事务管理等,还可以配置连接池的连接数、空闲时间等
一个MapConfig.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">
-
<!-- 事务的管理 JDBC MANAGED-->
-
<transactionManager type="JDBC"/>
-
<!-- 数据源 POOLED UNPOOLED JNDI -->
-
<dataSource type="POOLED">
-
<property name="driver" value="${driver}"/>
-
<property name="url" value="${url}"/>
-
<property name="username" value="${username}"/>
-
<property name="password" value="${password}"/>
-
</dataSource>
-
</environment>
-
</environments>
-
<mappers>
-
<mapper resource="org/mybatis/example/BlogMapper.xml"/>
-
</mappers>
-
</configuration>
mybatis mapper文件映射
<!-- 使用相对于类路径的资源引用 -->
-
<mappers>
-
<mapper resource="org/mybatis/builder/AuthorMapper.xml"/>
-
</mappers>
<!-- 使用映射器接口实现类的完全限定类名 mybais去加载class对应的接口,然后还会去加载该接口同目录下的同名xml文件 -->
-
<mappers>
-
<mapper class="org.mybatis.builder.AuthorMapper"/>
-
</mappers>
<!-- 将包内的映射器接口实现全部注册为映射器 使用package元素批量注册Mapper接口 1.包名和接口所在的包名字一致 2.mapper文件的名字和接口的名字一致 3.创建包是使用/分割 -->
-
<mappers>
-
<package name="org.mybatis.builder"/>
-
</mappers>
设置资源文件路径
Maven中默认是只会打包
resource下的资源文件。如果我们的文件不放在
resource, 则需要通过配置告知
Maven
-
<resources>
-
<resource>
-
<directory>src/main/java
</directory>
-
<includes>
-
<include>**/*.properties
</include>
-
<include>**/*.xml
</include>
-
</includes>
-
<filtering>false
</filtering>
-
</resource>
-
<resource>
-
<directory>src/main/resources
</directory>
-
<includes>
-
<include>**/*.properties
</include>
-
<include>**/*.xml
</include>
-
<include>**/*.tld
</include>
-
</includes>
-
<filtering>false
</filtering>
-
</resource>
-
</resources>
2.Sql映射文件
Mybatis中所有数据库的操作都会基于该映射文件和配置的sql语句,在这个配置文件中可以配置任何类型的sql语句。框架会根据配置文件中的参数配置,完成对sql语句以及输入输出参数的映射配置。
Mapper.xml配置文件大致如下:
-
<?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="命名空间">
-
-
<select id="方法名" resultMap="返回值类型" parameterType="参数类型">
-
-
-- sql语句
-
-
</select>
-
-
</mapper>
3.会话工厂与会话
Mybatis中会话工厂SqlSessionFactory类可以通过加载资源文件,读取数据源配置MapConfig.xml信息,从而产生一种可以与数据库交互的会话实例SqlSession,会话实例SqlSession根据Mapper.xml文件中配置的sql,对数据库进行操作。
4.运行流程
会话工厂SqlSessionFactory通过加载资源文件获取MapConfig.xml配置文件信息,然后生成可以与数据库交互的会话实例SqlSession。会话实例可以根据Mapper配置文件中的Sql配置去执行相应的增删改查操作
执行流程图:
mybatis实现增删改查
-
public
class
TestStudent {
-
-
@Test
-
public
void
test01
(){
-
-
try {
//加载配置文件
-
InputStream
in
= Resources.getResourceAsStream(
"config/mybatis-config.xml");
-
//获取sqlSession对象
-
SqlSession
sqlSession
=
new
SqlSessionFactoryBuilder().build(in).openSession();
-
//查询所有学生信息
-
List<Student> students = sqlSession.selectList(
"cn.kgc.mybatis.dao.StudentDao.getAll");
-
students.forEach(student -> System.out.println(student) );
-
}
catch (IOException e) {
-
e.printStackTrace();
-
}
-
}
-
-
@Test
-
public
void
test02
(){
//查询一个学生信息
-
-
try {
//加载配置文件
-
InputStream
in
= Resources.getResourceAsStream(
"config/mybatis-config.xml");
-
//获取sqlSession对象
-
SqlSession
sqlSession
=
new
SqlSessionFactoryBuilder().build(in).openSession();
-
//根据用户名查询一个学生信息
-
Student
student
= sqlSession.selectOne(
"cn.kgc.mybatis.dao.StudentDao.findOne",
"tom");
-
System.out.println(student);
-
sqlSession.close();
-
}
catch (IOException e) {
-
e.printStackTrace();
-
}
-
}
-
@Test
-
public
void
test03
() {
//添加一个学生信息
-
-
try {
//加载配置文件
-
InputStream
in
= Resources.getResourceAsStream(
"config/mybatis-config.xml");
-
//获取sqlSession对象
-
SqlSession
sqlSession
=
new
SqlSessionFactoryBuilder().build(in).openSession();
-
//添加一个学生信息
-
Student
student
= Student.builder().stuBirth(
new
Date()).stuName(
"lilei").stuNo(
"2021073001").stuSex(
"男").build();
-
int
i
= sqlSession.insert(
"cn.kgc.mybatis.dao.StudentDao.addOne", student);
-
System.out.println(i);
-
sqlSession.commit();
-
sqlSession.close();
-
-
}
catch (IOException e) {
-
e.printStackTrace();
-
}
-
-
}
-
@Test
-
public
void
test04
() {
//删除一个学生信息
-
-
try{
-
InputStream
in
= Resources.getResourceAsStream(
"config/mybatis-config.xml");
-
//获取sqlSession对象 同时可设置事务的自动提交 openSession(true)
-
SqlSession
sqlSession
=
new
SqlSessionFactoryBuilder().build(in).openSession();
-
int
delete
= sqlSession.delete(
"cn.kgc.mybatis.dao.StudentDao.delOne",
"lilei" );
-
sqlSession.commit();
-
sqlSession.close();
-
System.out.println(delete);
-
}
catch (Exception e){
-
e.printStackTrace();
-
}
-
-
}
-
-
@Test
-
public
void
test05
() {
//修改一个学生信息
-
-
try{
-
InputStream
in
= Resources.getResourceAsStream(
"config/mybatis-config.xml");
-
//获取sqlSession对象
-
SqlSession
sqlSession
=
new
SqlSessionFactoryBuilder().build(in).openSession();
-
-
Student
student
= Student.builder().stuBirth(
new
Date()).stuName(
"lili").stuNo(
"2021073001").stuSex(
"女").build();
-
int
delete
= sqlSession.update(
"cn.kgc.mybatis.dao.StudentDao.updateStudent",student);
-
sqlSession.commit();
-
sqlSession.close();
-
System.out.println(delete);
-
}
catch (Exception e){
-
e.printStackTrace();
-
}
-
-
-
}
-
-
}
-
mybatis中使用log4j日志工具
1.配置mybatis-config.xml
-
<!-- 开启日志-->
-
<setting name="logImpl" value="LOG4J"/>
开启驼峰命名
-
<!-- 设置驼峰命名-->
-
<setting name="mapUnderscoreToCamelCase" value="true"/>
设置别名
-
<typeAliases>
-
<!--设置别名-->
-
<package name="cn.kgc.mybatis.pojo"/>
-
</typeAliases>
2.配置log4j.properties文件,放置在resources目录下
-
log4j.rootLogger=DEBUG,Console
-
-
#Console
-
log4j.appender.Console=org.apache.log4j.ConsoleAppender
-
log4j.appender.console.Target=System.out
-
log4j.appender.Console.layout=org.apache.log4j.PatternLayout
-
log4j.appender.Console.layout.ConversionPattern=%d [%t] %-5p [%c] - %m%n
-
-
log4j.logger.org.apache=ERROR
-
log4j.logger.org.mybatis=ERROR
-
log4j.logger.org.springframework=ERROR
-
-
#这个需要
-
log4j.logger.log4jdbc.debug=ERROR
-
log4j.logger.com.gk.mapper=ERROR
-
log4j.logger.jdbc.audit=ERROR
-
log4j.logger.jdbc.resultset=ERROR
-
#这个打印SQL语句非常重要
-
log4j.logger.jdbc.sqlonly=DEBUG
-
log4j.logger.jdbc.sqltiming=ERROR
-
log4j.logger.jdbc.connection=FATAL
使用mapper代理对象实现增删改查
-
public
class
TestStudentMapper {
-
SqlSessionFactory factory;
-
@Before
-
public
void
init
(){
-
try {
-
InputStream
in
= Resources.getResourceAsStream(
"config/mybatis-config.xml");
-
SqlSessionFactoryBuilder
sfb
=
new
SqlSessionFactoryBuilder();
-
factory = sfb.build(in);
-
}
catch (IOException e) {
-
e.printStackTrace();
-
}
-
-
-
}
-
@Test
-
public
void
test01
(){
-
//开启事务自动提交
-
SqlSession
sqlSession
= factory.openSession(
true);
-
//获取dao层的代理对象
-
StudentDao
studentDao
= sqlSession.getMapper(StudentDao.class);
-
List<Student> students = studentDao.getAll();
-
students.forEach(student -> System.out.println(student));
-
}
-
-
@Test
-
public
void
test02
(){
//添加数据
-
-
SqlSession
sqlSession
= factory.openSession(
true);
-
Student
student
= Student.builder().stuSex(
"男").stuNo(
"2021073100").stuName(
"李四").stuBirth(
new
Date()).build();
-
StudentDao
studentDao
= sqlSession.getMapper(StudentDao.class);
-
Integer
line
= studentDao.addOne(student);
-
System.out.println(line);
-
}
-
-
@Test
-
public
void
test03
(){
//删除一条数据
-
SqlSession
sqlSession
= factory.openSession(
true);
-
StudentDao
studentDao
= sqlSession.getMapper(StudentDao.class);
-
Integer
line
= studentDao.delOne(
"李四");
-
System.out.println(line);
-
}
-
-
@Test
-
public
void
test04
() {
//修改数据
-
SqlSession
sqlSession
= factory.openSession(
true);
-
StudentDao
studentDao
= sqlSession.getMapper(StudentDao.class);
-
Student
student
= Student.builder().stuSex(
"女").stuNo(
"2021073100").stuName(
"李四").stuBirth(
new
Date()).build();
-
Integer
line
= studentDao.updateOne(student);
-
System.out.println(line);
-
-
}
-
-
@Test
-
public
void
test06
(){
//模糊查询一个学生信息 一个参数
-
SqlSession
sqlSession
= factory.openSession(
true);
-
StudentDao
studentDao
= sqlSession.getMapper(StudentDao.class);
-
-
List<Student> students = studentDao.selectLikeName(
"li");
-
System.out.println(students.toString());
-
-
}
-
-
@Test
-
public
void
test07
(){
//模糊查询一个学生信息 两个参数
-
SqlSession
sqlSession
= factory.openSession(
true);
-
StudentDao
studentDao
= sqlSession.getMapper(StudentDao.class);
-
-
List<Student> students = studentDao.selectLikeName2(
"li",
"2021072902");
-
System.out.println(students.toString());
-
-
-
}
-
@Test
-
public
void
test08
(){
//模糊查询一个学生信息 一个集合参数 mapper文件中按照key取值
-
SqlSession
sqlSession
= factory.openSession(
true);
-
StudentDao
studentDao
= sqlSession.getMapper(StudentDao.class);
-
-
HashMap<String, String> map =
new
HashMap<>();
-
map.put(
"stuname",
"li");
-
map.put(
"stuno",
"2021072902");
-
List<Student> students = studentDao.selectLikeName3(map);
-
System.out.println(students.toString());
-
}
-
-
}
-
Mybatis的获取参数的方式
方式1:${} 字符串拼接
方式2:#{} 占位符
1.Mapper接口参数为单个参数
-
<delete id="delUserById" parameterType="int">
-
delete from user where id = #{id}
-
</delete>
-
-
<delete id="delUserById" parameterType="int">
-
delete from user where id = ${id}
-
</delete>
注:如何参数是String类型使用${}获取参数是需要手动添加引号 ''
2.Mapper接口参数是多个参数的获取
mybatis在处理多个参数时,会将多个参数保存到map集合中会 以 agr0 ,agr1或param1 param2为键 以参数位置进行存储
-
User selectUserByUserNameAndPassword(String username,String password);
-
<select id="selectUserByUserNameAndPassword" resultType="user">
-
select * from user where user_name = #{arg0} and password = #{arg1}
-
</select>
3.将参数设为map集合进行数据的传递
-
User selectUserByMap(Map map);
-
<select id="selectUserByMap" resultType="cn.kgc.mybatis.entity.User">
-
select * from user where user_name = #{username} and password = #{password}
-
</select>
4.通过注解@param("键名")设置参数的获取名字
-
User selectUserByUserNameAndPassword(@param("username")String username,(@param("password")String password);
-
<select id="selectUserByUserNameAndPassword" resultType="user">
-
select * from user where user_name = #{username} and password = #{password}
-
</select>
-
-
或者
-
-
<select id="selectUserByUserNameAndPassword" resultType="user">
-
select * from user where user_name = #{param1} and password = #{param2}
-
</select>
-
5.将多个参数设置成对象进行数据的传递
-
int insertUser(User user);
-
<insert id="insertUser" parameterType="user" useGeneratedKeys="true" keyProperty="id" >
-
insert into user values ( #{id},#{userName},#{password})
-
</insert>
Mybatis中的模糊查询
方式1:
SELECT * FROM tableName WHERE name LIKE #{text}
-- 传递的参数需要拼接 ‘%text%’
方式2:
SELECT * FROM tableName WHERE name LIKE '%${text}%';
-- 使用$替代# 参数无需在拼接% 存在sql注入
方式3
SELECT * FROM tableName WHERE name LIKE CONCAT('%', #{text}), '%');
-- 使用mysql的函数 实现拼接
6.批量删除
-
int deleteMore(String ids);
-
<delete id="deleteMore">
-
delete from user where id in(${ids})
-
</delete>
mapper中自定义映射
自定义映射的用法之一,解决表格查询的字段名和实体类中不一致的情况
-
<resultMap id="userMap" type="user">
-
<id column="id" property="id">
</id>
-
<result column="user_name" property="userName">
</result>
-
<result column="password" property="password">
</result>
-
</resultMap>
mybatis对象的关联关系
一对多关系处理(一方)
-
<resultMap id="selectByEIdMap" type="cn.kgc.mybatis.entity.Emp">
-
<result column="id" property="dept.id" >
</result>
-
<result column="dname" property="dept.dName">
</result>
-
</resultMap>
-
-
-
<resultMap id="selectByEIdMap2" type="cn.kgc.mybatis.entity.Emp">
-
<id column="eid" property="eId">
</id>
-
<result column="ename" property="EName">
</result>
-
<result column="age" property="age">
</result>
-
<result column="deptno" property="deptNo">
</result>
-
<!--实体对象标识-->
-
<association property="dept" javaType="dept">
-
<id column="id" property="id">
</id>
-
<result column="dname" property="dName">
</result>
-
</association>
-
</resultMap>
-
-
<!-- 分步查询 -->
-
<resultMap id="selectByEIdMap3" type="cn.kgc.mybatis.entity.Emp">
-
<id column="eid" property="eId">
</id>
-
<result column="ename" property="EName">
</result>
-
<result column="age" property="age">
</result>
-
<result column="deptno" property="deptNo">
</result>
-
<association property="dept" select="cn.kgc.mybatis.mapper.DeptMapper.selectById"
-
column=
"deptno"
-
fetchType=
"eager">
-
</association>
-
</resultMap>
-
-
注:延迟加载设置 :
-
1.
<setting name="lazyLoadingEnabled" value="true"/>
-
2.
<setting name="aggressiveLazyLoading" value="false"/> 3.4.1之前的版本需要设置
-
-
<select id="selectByEId" resultMap="selectByEIdMap2">
-
select * from emp left join dept on emp.deptno = dept.id where eid = #{eid}
-
</select>
-
-
<select id="selectByEId2" resultMap="selectByEIdMap3">
-
select * from emp where eid = #{eid}
-
</select>
一对多关系处理(多方)
-
<resultMap id="BaseResultMap" type="cn.kgc.mybatis.entity.Dept">
-
<id property="id" column="id" />
-
<result property="dName" column="dname" />
-
<collection property="emps" ofType="emp">
-
<id column="eid" property="eId">
</id>
-
<result column="ename" property="EName">
</result>
-
<result column="age" property="age">
</result>
-
<result column="deptno" property="deptNo">
</result>
-
</collection>
-
</resultMap>
-
-
-
<resultMap id="BaseResultMap2" type="cn.kgc.mybatis.entity.Dept">
-
<id property="id" column="id" />
-
<result property="dName" column="dname" />
-
<collection property="emps" select="cn.kgc.mybatis.mapper.EmpMapper.selectByDeptId" column="id">
</collection>
-
</resultMap>
-
-
<select id="selectById" resultType="dept">
-
select * from dept where id = #{id}
-
</select>
-
-
<select id="selectById2" resultMap="BaseResultMap">
-
select emp.* ,dept.* from dept left join emp on dept.id = emp.deptno where id = #{id}
-
</select>
-
-
<select id="selectById3" resultMap="BaseResultMap2">
-
select dept.* from dept where id = #{id}
-
</select>
mybatis动态sql
动态 SQL 是 MyBatis 的强大特性之一。如果你使用过 JDBC 或其它类似的框架,你应该能理解根据不同条件拼接 SQL 语句有多痛苦,例如拼接时要确保不能忘记添加必要的空格,还要注意去掉列表最后一个列名的逗号。利用动态 SQL,可以彻底摆脱这种痛苦
动态SQL:if 语句
根据 stu_name 和 stu_sex 来查询数据。如果stu_name为空,那么将只根据stu_sex来查询;反之只根据stu_name来查询
首先不使用 动态SQL 来书写
-
<select id="selectStudent" resultType="student" parameterType="cn.kgc.mybatis.pojo.Student">
-
select * from user where stu_name=#{stu_name} and stu_sex=#{stu_sex}
-
</select>
可以发现,如果 #{stu_name} 为空,那么查询结果也是空,如何解决这个问题呢?使用 if 来判断
-
<select id="selectStudent" resultType="student" parameterType="cn.kgc.mybatis.pojo.Student">
-
select * from student where
-
<if test="stu_name != null">
-
stu_name=#{stu_name}
-
</if>
-
<if test="stu_sex!= null">
-
and stu_sex=#{stu_sex}
-
</if>
-
</select>
这样写我们可以看到,如果 sex 等于 null,那么查询语句为 select * from student where stu_name=#{stu_name},但是如果stu_name 为空呢?那么查询语句为 select * from user where and stu_sex=#{sex},这是错误的 SQL 语句,如何解决呢?
if+where 语句
-
<select id="selectStudent" resultType="student" parameterType="cn.kgc.mybatis.pojo.Student">
-
select * from student
-
<where>
-
<if test="stu_name != null">
-
stu_name=#{stu_name}
-
</if>
-
<if test="stu_sex!= null">
-
and stu_sex=#{stu_sex}
-
</if>
-
</where>
-
</select>
这个where标签会知道如果它包含的标签中有返回值的话,它就插入一个where。此外,如果标签返回的内容是以AND 或OR 开头的,则它会剔除掉
动态SQL:if+set 语句
上面的对于查询 SQL 语句包含 where 关键字,如果在进行更新操作的时候,含有 set 关键词
-
<update id="updateStudentById" parameterType="cn.kgc.mybatis.pojo.Student">
-
update student stu
-
<set>
-
<if test="stuname != null and stuname != ''">
-
stu.stu_name = #{stuName},
-
</if>
-
<if test="stusex != null and stusex != ''">
-
stu.stu_sex = #{stuSex}
-
</if>
-
</set>
-
where id=#{id}
-
</update>
-
如果第一个条件 username 为空,那么 sql 语句为:update user u set u.sex=? where id=?
-
如果第一个条件不为空,那么 sql 语句为:update user u set u.username = ? ,u.sex = ? where id=?
动态SQL:choose(when,otherwise) 语句
有时候,我们不想用到所有的查询条件,只想选择其中的一个,查询条件有一个满足即可,使用 choose 标签可以解决此类问题,类似于 Java 的 switch 语句
-
<select id="selectStudentByChoose" resultType="com.ys.po.User" parameterType="com.ys.po.User">
-
select * from student
-
<where>
-
<choose>
-
<when test="id !='' and id != null">
-
id=#{id}
-
</when>
-
<when test="username !='' and username != null">
-
and username=#{username}
-
</when>
-
<otherwise>
-
and sex=#{sex}
-
</otherwise>
-
</choose>
-
</where>
-
</select>
这里我们有三个条件,id,username,sex,只能选择一个作为查询条件
-
如果 id 不为空,那么查询语句为:select * from user where id=?
-
如果 id 为空,那么看username 是否为空,如果不为空,那么语句为 select * from user where username=?;
-
如果 username 为空,那么查询语句为 select * from user where sex=?
动态SQL:trim 语句
trim标记是一个格式化的标记,可以完成set或者是where标记的功能
用 trim 改写上面的 if+where 语句
-
<select id="selectStudent" resultType="student" parameterType="cn.kgc.mybatis.pojo.Student">
-
select * from user
-
<trim prefix="where" prefixOverrides=" and | or">
-
<if test="stu_name != null">
-
stu_name=#{stu_name}
-
</if>
-
<if test="stu_sex!= null">
-
and stu_sex=#{stu_sex}
-
</if>
-
</trim>
-
</select>
-
-
prefix:前缀
-
prefixoverride:去掉第一个and或者是or
用 trim 改写上面的 if+set 语句
-
<update id="updateStudentById" parameterType="cn.kgc.mybatis.pojo.Student">
-
update student stu
-
<trim prefix="set" suffixOverrides=",">
-
<if test="stuname != null and stuname != ''">
-
stu.stu_name = #{stuName},
-
</if>
-
<if test="stusex != null and stusex != ''">
-
stu.stu_sex = #{stuSex}
-
</if>
-
</trim>
-
where id=#{id}
-
</update>
-
suffix:后缀
-
suffixoverride:去掉最后一个逗号(也可以是其他的标记,就像是上面前缀中的and一样)
动态SQL: foreach 语句
需求:我们需要查询 user 表中 id 分别为1,2,3的用户,sql语句:
-
select
*
from
user
where id
=
1
or id
=
2
or id
=
3
-
-
select
*
from
user
where id
in (
1,
2,
3)
用 foreach 来改写 select * from user where id=1 or id=2 or id=3
-
<select id="selectUserByListId" parameterType="com.ys.vo.UserVo" resultType="com.ys.po.User">
-
select * from user
-
<where>
-
<!--
-
collection:指定输入对象中的集合属性
-
item:每次遍历生成的对象
-
open:开始遍历时的拼接字符串
-
close:结束时拼接的字符串
-
separator:遍历对象之间需要拼接的字符串
-
select * from user where 1=1 and (id=1 or id=2 or id=3)
-
-->
-
<foreach collection="ids" item="id" separator="or">
-
id=#{id}
-
</foreach>
-
</where>
-
</select>
用 foreach 来改写 select * from user where id in (1,2,3)
-
<select id="selectUserByListId" parameterType="com.ys.vo.UserVo" resultType="com.ys.po.User">
-
select * from user
-
<where>
-
<!--
-
collection:指定输入对象中的集合属性
-
item:每次遍历生成的对象
-
open:开始遍历时的拼接字符串
-
close:结束时拼接的字符串
-
separator:遍历对象之间需要拼接的字符串
-
select * from user where1=1 and id in (1,2,3)
-
-->
-
<foreach collection="ids" item="id" open="id in ("separator="," close=") " >
-
#{id}
-
</foreach>
-
</where>
-
</select>
动态SQL: SQL 片段
有时候可能某个 sql 语句我们用的特别多,为了增加代码的重用性,简化代码,我们需要将这些代码抽取出来,然后使用时直接调用。
假如我们需要经常根据用户名和性别来进行联合查询,那么我们就把这个代码抽取出来,如下:
-
<sql id="selectUserByUserNameAndSexSQL">
-
<if test="username != null and username != ''">
-
AND username = #{username}
-
</if>
-
<if test="sex != null and sex != ''">
-
AND sex = #{sex}
-
</if>
-
</sql>
-
<select id="selectUserByUsernameAndSex" resultType="user" parameterType="com.ys.po.User">
-
select * from user
-
<trim prefix="where" prefixOverrides="and | or">
-
<!-- 引用 sql 片段,如果refid 指定的不在本文件中,那么需要在前面加上 namespace -->
-
<include refid="selectUserByUserNameAndSexSQL">
</include>
-
<!-- 在这里还可以引用其他的 sql 片段 -->
-
</trim>
-
</select>
注意:
①、最好基于 单表来定义 sql 片段,提高片段的可重用性
②、在 sql 片段中最好不要包括 where
mybatis注解开发
-
public
interface
StudentDao2 {
-
-
@Select("select * from student where stu_no = #{stu_no}")
-
@Results({
-
@Result(property = "stuNo" ,column="stu_no"),
-
@Result(property = "stuSex",column = "stu_sex"),
-
@Result(property = "birth",column = "stu_birth")
-
})
-
List<Student>
getAll
(String stu_no);
-
-
@Insert("insert into student (stu_no,stu_name,stu_sex,stu_birth)values(#{stuNo},#{stuName},#{stuSex},#{birth})")
-
int
addStudent
(Student student);
-
-
@Delete("delete from student where stu_no = #{stu_no}")
-
int
delOne
(String stu_no);
-
-
@Update("update student set stu_name = #{stuName} where stu_no = #{stuNo}")
-
int
uptStudent
(Student student);
-
-
}
mybatis缓存
MyBatis 中的缓存就是说 MyBatis 在执行一次SQL查询或者SQL更新之后,这条SQL语句并不会消失,而是被MyBatis 缓存起来,当再次执行相同SQL语句的时候,就会直接从缓存中进行提取,而不是再次执行SQL命令。
mybatis的缓存机制有两级:
(1)一级缓存:一级缓存mybatsi已经为我们自动开启,不用我们手动操作,而且我们是关闭不了的!!但是我们可以手动清除缓存。(SqlSession级别.提交事务,缓存清空)
一级缓存失效的情况:
1.不同的SqlSession对应不同的缓存 2.同一个SqlSession但是查询条件不同 3.同一个SqlSession执行两次相同查询之间做了增删改的操作 4.同一个SqlSession执行两次相同查询之间手动清空缓存
(2)二级缓存:二级缓存需要我们手动开启。(全局级别 SqlSessionFactory)
<!--开启二级缓存--> 开启二级缓存需要两个步骤,第一步在mybatis的全局配置文件中配置Setting属性,设置名为cacheEnabled的属性值为true即可 <settings> <!-- (1):开启二级缓存,这个全局的配置二级缓存 默认是开启的,但是还是需要写上,防止版本的更新 --> <setting name="cacheEnabled" value="true"/> </settings> 第二步:在具体需要二级缓存的mapeer映射文件中开启二级缓存,值需要在相应的映射文件中添加一个cache标签即可 2):在相应的映射文件中开启二级缓存 <!-- 开启二级缓存 --> <cache></cache> 3)查询数据封装的实体类要实现序列化的接口 4)二级缓存需要在一级缓存关闭或者提交后生效 二级缓存失效的条件: 1.在两次查询之间进行了任意的增删改操作,一级二级缓存同时失效
-
@Test
-
public
void
test02
(){
//验证mybatis的缓存机制 一级缓存 默认开启 sqlsession级别
-
-
try {
-
InputStream
resource
= Resources.getResourceAsStream(
"config/mybatis-config.xml");
-
SqlSessionFactory
factory
=
new
SqlSessionFactoryBuilder().build(resource);
-
SqlSession
sqlSession
= factory.openSession(
true);
-
StudentDao
mapper1
= sqlSession.getMapper(StudentDao.class);
-
StudentDao
mapper2
= sqlSession.getMapper(StudentDao.class);
-
System.out.println(mapper1);
-
System.out.println(mapper2);
-
List<Student> a1 = mapper1.getAll();
-
System.out.println(a1);
-
//手动提交事务 清空缓存
-
sqlSession.commit();
-
List<Student> a2 = mapper2.getAll();
-
System.out.println(a2);
-
-
sqlSession.close();
-
}
catch (IOException e) {
-
e.printStackTrace();
-
}
-
}
-
-
-
@Test
-
public
void
test03
(){
//验证mybatis的缓存机制 二级缓存 需要配置mybatis-config.xml 和mapper文件
-
-
try {
-
InputStream
resource
= Resources.getResourceAsStream(
"config/mybatis-config.xml");
-
SqlSessionFactory
factory
=
new
SqlSessionFactoryBuilder().build(resource);
-
SqlSession
sqlSession1
= factory.openSession(
true);
-
SqlSession
sqlSession2
= factory.openSession(
true);
-
SqlSession
sqlSession3
= factory.openSession(
true);
-
-
StudentDao
mapper1
= sqlSession1.getMapper(StudentDao.class);
-
StudentDao
mapper2
= sqlSession2.getMapper(StudentDao.class);
-
StudentDao
mapper3
= sqlSession3.getMapper(StudentDao.class);
-
List<Student> a1 = mapper1.getAll();
-
System.out.println(a1);
-
//关闭session将查询结果写入二级缓存
-
sqlSession1.close();
-
-
//当对同一张表进行增删改操作后 二级缓存清除
-
mapper3.delStudent(
"2021072901");
-
// sqlSession3.close();
-
-
List<Student> a2 = mapper2.getAll();
-
System.out.println(a2);
-
-
}
catch (IOException e) {
-
e.printStackTrace();
-
}
-
}
mybatis分页插件
-
<!-- https://mvnrepository.com/artifact/com.github.pagehelper/pagehelper -->
-
<dependency>
-
<groupId>com.github.pagehelper
</groupId>
-
<artifactId>pagehelper
</artifactId>
-
<version>5.2.1
</version>
-
</dependency>
<!--在mybatis配置文件中 配置mybatis插件 -->
-
<plugins>
-
<plugin interceptor="com.github.pagehelper.PageInterceptor">
-
<!-- 配置mysql方言 -->
-
<property name="helperDialect" value="mysql" />
-
<!-- 设置为true时,如果pageSize=0就会查询出全部的结果 -->
-
<property name="pageSizeZero" value="true" />
-
<!-- 3.3.0版本可用,分页参数合理化,默认false禁用 -->
-
<!-- 启用合理化时,如果pageNum<1会查询第一页,如果pageNum>pages会查询最后一页 -->
-
<!-- 禁用合理化时,如果pageNum<1或pageNum>pages会返回空数据 -->
-
<property name="reasonable" value="true" />
-
</plugin>
-
</plugins>
实例
// 测试分页插件的使用
-
@Test
-
public
void
test06
(){
-
SqlSession
session
= factory.openSession(
true);
-
StudentDao
mapper
= session.getMapper(StudentDao.class);
-
PageHelper.startPage(
5,
3);
-
List<Student> all = mapper.findAll();
-
PageInfo<Student> pageInfo =
new
PageInfo<>(all);
-
-
//获取分页的相关数据
-
System.out.println(pageInfo);
-
//获取总条数
-
long
total
= pageInfo.getTotal();
-
System.out.println(total);
-
//获取当前页的显示数据
-
List<Student> list = pageInfo.getList();
-
list.forEach(student-> System.out.println(student));
-
-
}
转载:https://blog.csdn.net/m0_67979925/article/details/128975590