Mybatis

主流的ORM框架,之前叫IBatis后来叫MyBatis,实现数据持久化的框架,同时支持Java .NET, .Ruby三种语言,MyBatis是一个对JDBC进行封装的框架。

ORM 框架 Hibernate,两个的区别:

Hibernate是一个全自动化的ORM框架,MyBatis是一个半自动化的ORM框架

全自动化:开发者只需要调用相关接口就可以完成操作,整个流程框架都已经进行了封装。

Hibernate实现了POJO和数据库表之间的映射,同时可以自动生成SQL语句并完成执行。

半自动化:框架只提供一部分功能,剩下的工作仍需要开发者手动完成,MyBatis没有提供POJO与数据库表的映射,只实现了POJO与SQL的映射关系,需要开发者自定义SQL语句,以及数据与POJO之间的装配关系。

image-20240804170340405

虽然功能上没有Hibernate更加方便但是这种半自动化的方式提高了框架的灵活性

开发者可以根据具体的业务需求完成定制化的持久层解决方案

MyBatis对所有的JDBC进行了封装,包括参数设置,SQL执行,结果集的解析等,通过xml配置的方式或者注解的方式完成POJO与数据的映射。

简单来讲,使用Mybatis进行开发,主要完成两步操作:

  • 自己编写sql
  • 自己完成数据库数据与POJO的映射

MyBatis优点

  • 极大简化JDBC代码的开发
  • 简单好用容易上手,同时具有更好的灵活性
  • 通过将SQL定义在xml中的方式降低程序的耦合性
  • 支持动态SQL可以根据具体的业务需求灵活实现功能

MyBatis缺点

  • 相比于Hibernate,开发者需要完成更多工作比如定义SQL语句,设置POJO与数据的映射关系
  • 要求开发人员具备一定的SQL编写能力,在一些特定场景下工作量比较大
  • 数据库的移植性比较差,因为SQL依赖于底层数据库,部分SQL语句需要重新编写。

MyBatis入门

1、创建Maven工程,在pom.xml中引入依赖

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>com.bitzh</groupId>
<artifactId>mybatis</artifactId>
<version>1.0-SNAPSHOT</version>

<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<!--MyBatis-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.5</version>
</dependency>
<!--MySQL驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.19</version>
</dependency>
<!--lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.30</version>
</dependency>

</dependencies>

</project>

2、创建实体类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package com.bitzh.entity;

import lombok.Data;

/**
* @Auther: oyy0v0
* @Date: 2024/8/4 - 08 - 04 - 22:34
* @Description: com.bitzh.entity
* @version: 1.0
*/
@Data
public class People {
private Integer id;
private String name ;
private Double money;
}

3、配置MyBatis环境,在resources路径下创建config.xml(可以自定义),配置数据源信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?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>
<!--配置MyBatis运行环境-->
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<!--数据源,使用数据库连接池-->
<dataSource type="POOLED">
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/test?useUnicode=true&amp;characterEncoding=utf8&amp;useSSL=false&amp;serverTimezone=UTC"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
<!--配两个环境,一个用测试数据库一个运行数据库但是现在只有一个就行-->
<!--<environment id="">
<transactionManager type=""></transactionManager>
<dataSource type=""></dataSource>
</environment>-->
</environments>

</configuration>

4、MyBatis 开发有两种方式

  • 使用原生接口
  • Mapper代理实现自定义接口

使用原生接口

1、创建Mapper文件PeopleMapper.xml

1
2
3
4
5
6
7
8
9
10
<?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.bitzh.mapper.PeopleMapper">
<select id="findById" parameterType="java.lang.Integer" resultType="com.bitzh.entity.People">
select * from people where id = #{id}
</select>

</mapper>

namespace:通常设置为文件所在包的包名+文件名,parameterType是参数的数据类型

resultType:是返回值的数据类型

2、在全局配置文件config.xml中注册PeopleMapper.xml

1
2
3
<mappers>
<mapper resource="com/bitzh/mapper/PeopleMapper.xml"></mapper>
</mappers>

3、调用api完成操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
package com.bitzh.test;

import com.bitzh.entity.People;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.InputStream;

/**
* @Auther: oyy0v0
* @Date: 2024/8/5 - 08 - 05 - 17:37
* @Description: com.bitzh.test
* @version: 1.0
*/
public class Test {
//这是一个main方法,是程序的入口
public static void main(String[] args) {
//加载MyBatis配置文件
InputStream inputStream = Test.class.getClassLoader().getResourceAsStream("config.xml");
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(inputStream);
//获取 SqlSession
SqlSession sqlSession = sqlSessionFactory.openSession();
//调用MyBatis原生接口来执行SQL语句
String statement = "com.bitzh.mapper.PeopleMapper.findById";
People people = sqlSession.selectOne(statement, 1);
System.out.println(people);
sqlSession.close();
}
}

4、IDEA中无法直接读取resources路径下的xml文件需要再pom.xml中进行设置

1
2
3
4
5
6
7
8
9
10
<build>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
</includes>
</resource>
</resources>
</build>

Mapper代理实现自定义接口

开发者只需要定义接口,并不需要实现接口,具体的实现工作由Mapper代理结合配置文件完成。

1、自定义接口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package com.bitzh.repository;

import com.bitzh.entity.People;

import java.util.List;

/**
* @Auther: oyy0v0
* @Date: 2024/8/5 - 08 - 05 - 18:09
* @Description: com.bitzh.repository
* @version: 1.0
*/
public interface PeopleRepository {
public int save(People people);
public int deleteById(Integer id);
public int update(People people);
public People findById(Integer id);
public List<People> findAll();
}

2、创建PeopleMapper.xml定义接口方法对应的SQL语句statement标签根据SQL执行的业务可以选择select\insert\delete\update,MyBatis会根据规则创建PeopleRepository接口的实现类代理对象。

规则如下:

  • PeopleMapper.xml中的namespace必须是接口的全限定类名(带着包名的类名)
  • PeopleMapper.xml中的statement的id是接口中对应的方法名
  • PeopleMapper.xml中parameterType和接口中对应方法的参数类型一致
  • PeoplMapper.xml中的resultType和接口中对应方法的返回值类型一致
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<?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.bitzh.repository.PeopleRepository">
<insert id="save" parameterType="com.bitzh.entity.People">
insert into people values(default,#{name},#{money})
</insert>
<delete id="deleteById" parameterType="java.lang.Integer">
delete from people where id = #{id}
</delete>
<update id="update" parameterType="com.bitzh.entity.People">
update people set name = #{name},money = #{money} where id = #{id}
</update>
<select id="findById" parameterType="java.lang.Integer" resultType="com.bitzh.entity.People">
select * from people where id = #{id}
</select>
<select id="findAll" resultType="com.bitzh.entity.People">
select * from people
</select>

</mapper>

3、完成注册

1
2
3
4
<mappers>
<mapper resource="com/bitzh/mapper/PeopleMapper.xml"></mapper>
<mapper resource="com/bitzh/repository/PeopleRepository.xml"></mapper>
</mappers>

4、调用api

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
package com.bitzh.test;

import com.bitzh.entity.People;
import com.bitzh.repository.PeopleRepository;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.InputStream;
import java.util.List;

/**
* @Auther: oyy0v0
* @Date: 2024/8/5 - 08 - 05 - 18:32
* @Description: com.bitzh.test
* @version: 1.0
*/
public class Test2 {
//这是一个main方法,是程序的入口
public static void main(String[] args) {
InputStream inputStream = Test2.class.getClassLoader().getResourceAsStream("config.xml");
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(inputStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
//获取实现了自定义接口的代理对象
PeopleRepository peopleRepository = sqlSession.getMapper(PeopleRepository.class);
/* People people = new People();
people.setName("小明");
people.setMoney(Double.parseDouble("666"));
int rows = peopleRepository.save(people);
System.out.println(rows);*/
/*People people = peopleRepository.findById(5);
System.out.println(people);*/

List<People> list = peopleRepository.findAll();
for(People people:list){
System.out.println(people);
}

sqlSession.commit();
sqlSession.close();
}
}

Mapper.xml常用配置

MyBatis的配置文件有两种

  • 全局环境配置文件(数据源,事务管理,mapper的注册,打印sql,惰性加载,二级缓存。。。)
  • Mapper配置文件(定义自定义接口的具体实现方案,sql,数据与pojo的映射)

多表关联查询包括一对一,一对多,多对多三种

单表查询

1
2
3
<select id="findById" parameterType="java.lang.Integer" resultType="com.bitzh.entity.People">
select * from people where id = #{id}
</select>

业务:通过id查询People对象

目标表:test/people

实体类:com.bitzh.entity.People

Mapper.xml直接拍每个设置相关配置逻辑,用MyBatis自动完成查询,生成POJO

statement标签主要属性有id、parameterType、resultType

id对应接口方法名,parameterType定义参数的数据类型,resultType定义查询结果的数据类型(实体类的成员变量列表必须与目标表的字段列表一致)

parameterType

支持基本数据类型、包装类、String、多参数、POJO等。

1、基本数据类型,通过id查询POJO。

1
public People findById(int id);
1
2
3
<select id="findById" parameterType="int" resultType="com.bitzh.entity.People">
select * from people id = #{id}
</select>

2、包装类

1
2
3
<select id="findById" parameterType="java.lang.Integer" resultType="com.bitzh.entity.People">
select * from people where id = #{id}
</select>

3、String类型

1
public People findByName(String name);
1
2
3
<select id="findByName" parameterType="java.lang.String" resultType="com.bitzh.entity.People">
select * from people where name = #{name}
</select>

4、多参数、

1
public People findByIdAndName(Integer id,String name);
1
2
3
<select id="findByIdAndName" resultType="com.bitzh.entity.People">
select * from people where id=#{param1} and name=#{param2}
</select>

5、POJO

也是一样的

resultType

resultType与parameter的使用基本一致

多表关联查询

实际开发中最常用的是:一对多和多对多

一对多

1、建表

1
2
3
4
5
6
7
8
9
10
11
12

create table t_classes(
id int(11) not null primary key auto_increment,
name varchar(11) default NULL
);

create table t_student(
id int(11) not null primary key auto_increment,
name varchar(11) default null,
cid int(11) default null,
constraint t_student_ibfk foreign key (cid) references t_classes(id)
);

2、SQL

1
2
3
4
5
select s.id sid ,s.name sname,s.cid,t.name cname
from t_student s
inner join t_classes t
on s.cid = t.id
where s.id = 1

3、创建实体类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package com.bitzh.entity;

import lombok.Data;

/**
* @Auther: oyy0v0
* @Date: 2024/8/5 - 08 - 05 - 21:44
* @Description: com.bitzh.entity
* @version: 1.0
*/
@Data
public class Student {
private Integer id;
private String name;
private Classes classes;
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package com.bitzh.entity;

import lombok.Data;

/**
* @Auther: oyy0v0
* @Date: 2024/8/5 - 08 - 05 - 21:45
* @Description: com.bitzh.entity
* @version: 1.0
*/
@Data
public class Classes {
private Integer id;
private String name;
private List<Student> student;
}

4、StudentRepository接口

1
2
3
public interface StudentRepository {
public Student findById(Integer id);
}

5、StudentRepository.xml

resultType直接将结果集与实体类进行映射,结果集的字段名与实体类的成员变量名相等则映射。

resultMap 可以对结果集进行二次封装,根据需求来完成结果集数据到实体类的映射。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<?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.bitzh.repository.StudentRepository">
<resultMap id="studentMap" type="com.bitzh.entity.Student">
<id column="sid" property="id"></id>
<result column="sname" property="name"></result>
<association property="classes" javaType="com.bitzh.entity.Classes">
<id column="cid" property="id"></id>
<result column="cname" property="name"></result>
</association>
</resultMap>

<select id="findById" parameterType="java.lang.Integer" resultMap="studentMap" >
select s.id sid ,s.name sname,s.cid,t.name cname
from t_student s
inner join t_classes t
on s.cid = t.id
where s.id = 1
</select>
</mapper>

6、ClassesRepository

1
2
3
4
public interface ClassesRepository {
public Classes findById(Integer id);

}

7、ClassesRepository.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?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.bitzh.repository.ClassesRepository">
<resultMap id="classesMap" type="com.bitzh.entity.Classes">
<id column="cid" property="id"></id>
<result column="cname" property="name"></result>
<collection property="student" ofType="com.bitzh.entity.Student">
<id property="id" column="sid"></id>
<result column="sname" property="name"></result>
</collection>
</resultMap>
<select id="findById" parameterType="java.lang.Integer" resultMap="classesMap">
select c.id cid,c.name cname,s.id sid,s.`name` sname
from t_classes c
inner join t_student s
on c.id = s.cid
where c.id = 1
</select>


</mapper>

collection和association的区别

collection是将结果集封装成一个集合对象(多个目标对象)

association是将结果集封装成一个实体类的对象(一个目标对象)

collection是对ofType设置数据类型,association是通过javaType设置数据类型。

多对多

多对多是双向的一对多关系,(学生选课)

1、建表(多对多外键不能加在任意一张表要新建一个中间表)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
create table t_account(
id int(11) not null primary key auto_increment,
name varchar(11) default NULL
);
create table t_course(
id int(11) not null primary key auto_increment,
name varchar(11) default null
);
create table account_course(
id int(11) not null primary key auto_increment,
aid int(11) default null,
cid int(11) default null,
constraint account_course_ibfk_1 foreign key (aid) references t_account(id),
constraint account_course_ibfk_2 foreign key (cid) references t_course(id)
);

2、创建实体类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package com.bitzh.entity;


import lombok.Data;

import java.util.List;

/**
* @Auther: oyy0v0
* @Date: 2024/8/6 - 08 - 06 - 9:25
* @Description: com.bitzh.entity
* @version: 1.0
*/
@Data
public class Course {
private Integer id;
private String name;
List<Account> accounts;
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package com.bitzh.entity;

import lombok.Data;

import java.util.List;

/**
* @Auther: oyy0v0
* @Date: 2024/8/6 - 08 - 06 - 9:25
* @Description: com.bitzh.entity
* @version: 1.0
*/
@Data
public class Account {
private Integer id;
private String name;
private List<Course> courses;
}

3、AccountRepository

1
2
3
public interface AccountRepository {
public Account findById(Integer id);
}

4、AccountRepository.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<?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.bitzh.repository.AccountRepository">
<resultMap id="accountMap" type="com.bitzh.entity.Account">
<id column="aid" property="id"></id>
<result column="aname" property="name"></result>
<collection property="courses" ofType="com.bitzh.entity.Course">
<id column="cid" property="id"></id>
<result column="cname" property="name"></result>
</collection>
</resultMap>
<select id="findById" parameterType="java.lang.Integer" resultMap="accountMap">
select a.id aid,a.name aname,c.id cid,c.`name` cname
from account_course ac
inner join t_course c
on c.id = ac.cid
inner join t_account a
on a.id = ac.aid
where a.id=1;
</select>



</mapper>

5、CourseRepository

1
2
3
4
5
6
7
8
9
10
11
12
13
14
package com.bitzh.repository;

import com.bitzh.entity.Course;

/**
* @Auther: oyy0v0
* @Date: 2024/8/6 - 08 - 06 - 10:19
* @Description: com.bitzh.repository
* @version: 1.0
*/
public interface CourseRepository {
public Course findById(Integer id);
}

6、CourseRepository.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<?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.bitzh.repository.CourseRepository">
<resultMap id="courseMap" type="com.bitzh.entity.Course">
<id column="cid" property="id"></id>
<result column="cname" property="name"></result>
<collection property="accounts" ofType="com.bitzh.entity.Account">
<id column="aid" property="id"></id>
<result column="aname" property="name"></result>
</collection>
</resultMap>
<select id="findById" parameterType="java.lang.Integer" resultMap="courseMap">
select a.id aid,a.name aname,c.id cid,c.`name` cname
from account_course ac
inner join t_course c
on c.id = ac.cid
inner join t_account a
on a.id = ac.aid
where c.id=1
</select>


</mapper>

Mybatis逆向工程

MyBatis是半自动化的ORM框架,SQL语句需要开发者自定义,SQL需要单独定义在Mapper.xml中,需要与Mapper接口对应,使用MyBatis进行开发的基本配置:

  • 实体类
  • Mapper接口
  • Mapper.xml

image-20240806151156227

这种方法的缺陷是如果参与业务的表太多,每张表的业务都需要自定义SQL语句,创建实体类,以及Mapper接口,工作量较大。

MyBatis框架可以自动根据数据表帮助开发者生成实体类,Mapper接口,Mapper.xml,这就是逆向工程。

逆向工程概念

逆向工程是MyBatis提供的一种自动化配置方案,针对数据表自动生成MyBatis所需要的各种资源(实体类,Mapper接口,Mapper.xml)但是逆向工程化只针对于单表,如果数据表之间有级联关系,逆向工程无法自动生成级联关系。

使用逆向工程

MyBatis逆向工程的组件是MyBatis Generator,简称MBG,是专门为MyBatis框架定值的代码自动生成解决方案,MBG可以根据数据表结构快速生成对应的实体类,Mapper接口,Mapper.xml,并且支持基本的CRUD操作,但是业务逻辑相对复杂的操作需要手动完成

1、创建Maven工程,pom.xml添加相关依赖

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<dependencies>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.5</version>
</dependency>

<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.19</version>
</dependency>

<dependency>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-core</artifactId>
<version>1.3.2</version>
</dependency>

</dependencies>

2、创建目标表Account

1
2
3
4
5
6
7
CREATE TABLE `t_account` (
`id` int NOT NULL AUTO_INCREMENT,
`name` varchar(11) DEFAULT NULL,
`password` varchar(11) DEFAULT NULL,
`age` int DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci

3、创建MBG配置文件generatorConfig.xml

  • jdbcConnection配置数据库链接信息
  • javaModelGenerator配置javaBean的生成策略
  • sqlMapGenerator配置SQL映射文件生成策略
  • javaClientGenerator配置Mapper接口的生成策略
  • table配置需要逆向解析的数据表(tableName:表名,domainObjectName:实体类名)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
"http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<!--上面爆红可以不用管-->
<generatorConfiguration>
<!--
targetRuntime: 执行生成的逆向工程的版本
MyBatis3Simple: 生成基本的CRUD(清新简洁版 增删改)
MyBatis3: 生成带条件的CRUD(奢华尊享版 )
-->
<context id="testTables" targetRuntime="MyBatis3">
<!-- 数据库的连接信息 -->
<jdbcConnection driverClass="com.mysql.cj.jdbc.Driver"
connectionURL="jdbc:mysql://localhost:3306/test?useUnicode=true&amp;characterEncoding=utf8&amp;useSSL=false&amp;serverTimezone=UTC"
userId="root"
password="root">
</jdbcConnection>
<!-- javaBean的生成策略-->
<javaModelGenerator targetPackage="com.bitzh.entity" targetProject=".\src\main\java"></javaModelGenerator>
<!-- SQL映射文件的生成策略 -->
<sqlMapGenerator targetPackage="com.bitzh.repository" targetProject=".\src\main\java"></sqlMapGenerator>
<!-- Mapper接口的生成策略 -->
<javaClientGenerator type="XMLMAPPER" targetPackage="com.bitzh.repository" targetProject=".\src\main\java"></javaClientGenerator>
<!-- 逆向分析的表 -->
<!-- tableName设置为*号,可以对应所有表,此时不写domainObjectName -->
<!-- domainObjectName属性指定生成出来的实体类的类名 -->
<table tableName="t_account" domainObjectName="Account"/>
</context>
</generatorConfiguration>

4、创建GeneratorMain类,执行自动生成资源代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
package com.bitzh.test;

/**
* @Auther: oyy0v0
* @Date: 2024/8/6 - 08 - 06 - 15:43
* @Description: com.bitzh.test
* @version: 1.0
*/

import java.io.File;
import java.io.IOException;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import org.mybatis.generator.api.MyBatisGenerator;
import org.mybatis.generator.config.Configuration;
import org.mybatis.generator.config.xml.ConfigurationParser;
import org.mybatis.generator.exception.InvalidConfigurationException;
import org.mybatis.generator.exception.XMLParserException;
import org.mybatis.generator.internal.DefaultShellCallback;

public class GeneratorMain {
public static void main(String[] args) {
List<String> warnings = new ArrayList<>();
boolean overwrite = true;
String genCig = "/generatorConfig.xml";
File configFile = new File(GeneratorMain.class.getResource(genCig).getFile());
ConfigurationParser configurationParser = new ConfigurationParser(warnings);
Configuration configuration = null;
try {
configuration = configurationParser.parseConfiguration(configFile);
} catch (IOException e) {
e.printStackTrace();
} catch (XMLParserException e) {
e.printStackTrace();
}
DefaultShellCallback callback = new DefaultShellCallback(overwrite);
MyBatisGenerator myBatisGenerator = null;
try {
myBatisGenerator = new MyBatisGenerator(configuration, callback, warnings);
} catch (InvalidConfigurationException e) {
e.printStackTrace();
}
try {
myBatisGenerator.generate(null);
} catch (SQLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

MyBatis延迟加载

1、创建实体类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package com.bitzh.entity;

import lombok.Data;

import java.util.List;

/**
* @Auther: oyy0v0
* @Date: 2024/8/6 - 08 - 06 - 16:17
* @Description: com.bitzh.entity
* @version: 1.0
*/
@Data
public class Customer {
private Integer id;
private String name;
List<Order> orders;
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package com.bitzh.entity;

import lombok.Data;

/**
* @Auther: oyy0v0
* @Date: 2024/8/6 - 08 - 06 - 16:18
* @Description: com.bitzh.entity
* @version: 1.0
*/
@Data
public class Order {
private Integer id;
private String name;
private Customer customer;
}

2、配置打印sql,在config,xml中

1
2
3
4
<settings>
<!-- 打印sql日志 -->
<setting name="logImpl" value="STDOUT_LOGGING" />
</settings>

3、创建OrderRepository

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<?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.bitzh.repository.OrderRepository">

<resultMap id="orderMap" type="com.bitzh.entity.Order">
<id column="id" property="id"></id>
<result column="name" property="name"></result>
<association
property="customer"
javaType="com.bitzh.entity.Customer"
select="com.bitzh.repository.CustomerRepository.findById"
column="cid"
></association>
</resultMap>
<select id="findById" parameterType="java.lang.Integer" resultMap="orderMap">
select * from orders where id = #{id}
</select>


</mapper>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
package com.bitzh.repository;

import com.bitzh.entity.Order;

/**
* @Auther: oyy0v0
* @Date: 2024/8/6 - 08 - 06 - 16:21
* @Description: com.bitzh.repository
* @version: 1.0
*/
public interface OrderRepository {
public Order findById(Integer id);
}

4、创建CustomerRepository

1
2
3
4
5
6
7
8
9
10
<?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.bitzh.repository.CustomerRepository">

<select id="findById" parameterType="java.lang.Integer" resultType="com.bitzh.entity.Customer">
select * from customers where id = #{id}
</select>

</mapper>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
package com.bitzh.repository;

import com.bitzh.entity.Customer;

/**
* @Auther: oyy0v0
* @Date: 2024/8/6 - 08 - 06 - 16:32
* @Description: com.bitzh.repository
* @version: 1.0
*/
public interface CustomerRepository {
public Customer findById(Integer id);
}

5、config.xml中开启延迟加载

1
2
3
4
5
6
<settings>
<!-- 打印sql日志 -->
<setting name="logImpl" value="STDOUT_LOGGING" />
<!--延迟加载-->
<setting name="lazyLoadingEnabled" value="true"/>
</settings>

如果设置懒加载后报错可能是mybatis版本太低!

image-20240806170343323

image-20240806170505164

MyBatis延迟加载机制,实际开发中使用频率较高的一个功能,正确的使用延迟加载,可以有效的减少java Application和数据库的交互次数,从而提高整个系统的运行效率,延迟加载是为了提高程序运行效率的一种手段,一般应用于多表关联查询的业务场景。

MyBatis缓存

使用缓存的作用也是为了减少Java Application与数据库的交互次数,从而提升程序的运行效率。

image-20240806171533806

MyBatis有两种缓存:一级缓存和二级缓存。

一级缓存

MyBatis自带一级缓存,并且是无法关闭的,一直存在,一级缓存的数据存储在SqlSession中。

即使用同一个SqlSession进行查询操作的时候,一级缓存存在,如果说使用多个SqlSession进行查询操作,一级缓存不存在,缓存只针对于查询操作但是如果SqlSession执行了增删改操作,那么MyBatis会自动清空SqlSession缓存中的数据,以此来保证数据的一致性。

一级缓存不需要进行任何配置,直接使用即可。

1、创建实体类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package com.bitzh.entity;

import lombok.Data;

/**
* @Auther: oyy0v0
* @Date: 2024/8/6 - 08 - 06 - 17:52
* @Description: com.bitzh.entity
* @version: 1.0
*/
@Data
public class MyClass {
private Integer id;
private String name;
}

2、创建Mapper接口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
package com.bitzh.repository;

import com.bitzh.entity.MyClass;

/**
* @Auther: oyy0v0
* @Date: 2024/8/6 - 08 - 06 - 17:53
* @Description: com.bitzh.repository
* @version: 1.0
*/
public interface MyClassRepository {
public MyClass findById(Integer id);
}

3、创凯MyClassRepository.xml

1
2
3
4
5
6
7
8
9
10
11
<?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.bitzh.repository.MyClassRepository">

<select id="findById" parameterType="java.lang.Integer" resultType="com.bitzh.entity.MyClass">
select * from t_classes where id =#{id}
</select>


</mapper>

image-20240806175900499

如图开了一级缓存执行了一次sql语句。

如果关闭sqlSession,开启新的sqlSession的话,sql语句就会执行两次。

二级缓存

MyBatis二级缓存是比一级缓存作用域更大的缓存机制,它是Mapper级别的,只要是同一个Mapper,无论使用了多少个SqlSession,数据都是共享的。

image-20240806172730480

MyBatis二级缓存默认是关闭的,需要使用时

可以通过配置手动开启。

MyBatis可以使用自带的二级缓存,也可以使用第三方的ehcache二级缓存。

自带的二级缓存

1、config.xml中配置开启二级缓存

1
2
<!--开启二级缓存-->
<setting name="cacheEnabled" value="true"/>

2、在Mapper.xml中配置二级缓存

1
2
3
4
5
6
7
8
9
10
11
12
<?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.bitzh.repository.MyClassRepository">

<cache></cache>
<select id="findById" parameterType="java.lang.Integer" resultType="com.bitzh.entity.MyClass">
select * from t_classes where id =#{id}
</select>


</mapper>

3、实体类实现序列化接口Serializable

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package com.bitzh.entity;

import lombok.Data;

import java.io.Serializable;

/**
* @Auther: oyy0v0
* @Date: 2024/8/6 - 08 - 06 - 17:52
* @Description: com.bitzh.entity
* @version: 1.0
*/
@Data
public class MyClass implements Serializable {
private Integer id;
private String name;
}

4、测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
package com.bitzh.test;

import com.bitzh.entity.MyClass;
import com.bitzh.entity.Order;
import com.bitzh.repository.MyClassRepository;
import com.bitzh.repository.OrderRepository;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.InputStream;

/**
* @Auther: oyy0v0
* @Date: 2024/8/5 - 08 - 05 - 21:50
* @Description: com.bitzh.test
* @version: 1.0
*/
public class Test6 {
//这是一个main方法,是程序的入口
public static void main(String[] args) {
InputStream inputStream = Test2.class.getClassLoader().getResourceAsStream("config.xml");
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(inputStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
MyClassRepository myClassRepository = sqlSession.getMapper(MyClassRepository.class);
MyClass myClass = myClassRepository.findById(1);
System.out.println(myClass);
sqlSession.close();
SqlSession sqlSession2 = sqlSessionFactory.openSession();
MyClassRepository myClassRepository2 = sqlSession2.getMapper(MyClassRepository.class);
MyClass myClass2 = myClassRepository2.findById(1);
System.out.println(myClass2);
sqlSession.close();
}
}

image-20240806181013748

第三方ehcache二级缓存

1、pom.xml

1
2
3
4
5
6
7
8
9
10
11
<!--ehcache-->
<dependency>
<groupId>net.sf.ehcache</groupId>
<artifactId>ehcache-core</artifactId>
<version>2.4.3</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-ehcache</artifactId>
<version>1.0.0</version>
</dependency>

2、resources路径下创建ehcache.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd"
updateCheck="false">
<!--
diskStore:为缓存路径,ehcache分为内存和磁盘两级,此属性定义磁盘的缓存位置。参数解释如下:
user.home – 用户主目录
user.dir – 用户当前工作目录
java.io.tmpdir – 默认临时文件路径
-->
<!--<diskStore path="java.io.tmpdir/Tmp_EhCache"/>-->
<diskStore/>
<!--
defaultCache:默认缓存策略,当ehcache找不到定义的缓存时,则使用这个缓存策略。只能定义一个。
-->
<!--
name:缓存名称。
maxElementsInMemory:缓存最大数目
maxElementsOnDisk:硬盘最大缓存个数。
eternal:对象是否永久有效,一但设置了,timeout将不起作用。
overflowToDisk:是否保存到磁盘,当系统当机时
timeToIdleSeconds:设置对象在失效前的允许闲置时间(单位:秒)。仅当eternal=false对象不是永久有效时使用,可选属性,默认值是0,也就是可闲置时间无穷大。
timeToLiveSeconds:设置对象在失效前允许存活时间(单位:秒)。最大时间介于创建时间和失效时间之间。仅当eternal=false对象不是永久有效时使用,默认是0.,也就是对象存活时间无穷大。
diskPersistent:是否缓存虚拟机重启期数据 Whether the disk store persists between restarts of the Virtual Machine. The default value is false.
diskSpoolBufferSizeMB:这个参数设置DiskStore(磁盘缓存)的缓存区大小。默认是30MB。每个Cache都应该有自己的一个缓冲区。
diskExpiryThreadIntervalSeconds:磁盘失效线程运行时间间隔,默认是120秒。
memoryStoreEvictionPolicy:当达到maxElementsInMemory限制时,Ehcache将会根据指定的策略去清理内存。默认策略是LRU(最近最少使用)。你可以设置为FIFO(先进先出)或是LFU(较少使用)。
clearOnFlush:内存数量最大时是否清除。
memoryStoreEvictionPolicy:可选策略有:LRU(最近最少使用,默认策略)、FIFO(先进先出)、LFU(最少访问次数)。
FIFO,first in first out,这个是大家最熟的,先进先出。
LFU, Less Frequently Used,就是上面例子中使用的策略,直白一点就是讲一直以来最少被使用的。如上面所讲,缓存的元素有一个hit属性,hit值最小的将会被清出缓存。
LRU,Least Recently Used,最近最少使用的,缓存的元素有一个时间戳,当缓存容量满了,而又需要腾出地方来缓存新的元素的时候,那么现有缓存元素中时间戳离当前时间最远的元素将被清出缓存。
-->
<defaultCache
eternal="false"
maxElementsInMemory="10000"
overflowToDisk="false"
diskPersistent="false"
timeToIdleSeconds="1800"
timeToLiveSeconds="259200"
memoryStoreEvictionPolicy="LRU"/>
<!--<cache
name="cloud_user"
eternal="false"
maxElementsInMemory="5000"
overflowToDisk="false"
diskPersistent="false"
timeToIdleSeconds="1800"
timeToLiveSeconds="1800"
memoryStoreEvictionPolicy="LRU"/>-->

</ehcache>

3、config.xml中配置二级缓存

1
2
<!--开启二级缓存-->
<setting name="cacheEnabled" value="true"/>

4、Mapper.xml中配置二级缓存。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<?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.bitzh.repository.MyClassRepository">

<!--开启二级缓存-->
<cache type="org.mybatis.caches.ehcache.EhcacheCache">
<!--缓存创建以后,最后一次访问缓存的时间到失效的时间间隔-->
<property name="timeToIdleSeconds" value="3600"/>
<!--缓存自创建时间起至失效的时间间隔-->
<property name="timeToLiveSeconds" value="3600"/>
<!--缓存回收策略,LRU移除近期最少使用的对象-->
<property name="memoryStoreEvictionPolicy" value="LRU"/>
</cache>

<select id="findById" parameterType="java.lang.Integer" resultType="com.bitzh.entity.MyClass">
select * from t_classes where id =#{id}
</select>


</mapper>

5、实体类不需要实现序列化接口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package com.bitzh.entity;

import lombok.Data;

import java.io.Serializable;

/**
* @Auther: oyy0v0
* @Date: 2024/8/6 - 08 - 06 - 17:52
* @Description: com.bitzh.entity
* @version: 1.0
*/
@Data
public class MyClass {
private Integer id;
private String name;
}

6、测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
package com.bitzh.test;

import com.bitzh.entity.MyClass;
import com.bitzh.repository.MyClassRepository;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.InputStream;

/**
* @Auther: oyy0v0
* @Date: 2024/8/5 - 08 - 05 - 21:50
* @Description: com.bitzh.test
* @version: 1.0
*/
public class Test6 {
//这是一个main方法,是程序的入口
public static void main(String[] args) {
InputStream inputStream = Test3.class.getClassLoader().getResourceAsStream("config.xml");
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(inputStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
MyClassRepository myClassRepository = sqlSession.getMapper(MyClassRepository.class);
MyClass myClass = myClassRepository.findById(1);
System.out.println(myClass);
sqlSession = sqlSessionFactory.openSession();
myClassRepository = sqlSession.getMapper(MyClassRepository.class);
MyClass myClass2 = myClassRepository.findById(1);
System.out.println(myClass2);
sqlSession.close();
}
}

image-20240807020326231

MyBatis动态SQL

  • 通过id和username查询user
  • 通过username和password查询user
  • 通过password和age查询user

在userRepository中定义上述三个方法

UserRepository.xml

1
2
3
4
5
6
7
8
9
<select id="findByUser1" parameterType="User" resultType="User">
select * from t_user where id = #{id} and username = #{username}
</select>
<select id="findByUser2" parameterType="User" resultType="User">
select * from t_user where username = #{username} and password = #{password}
</select>
<select id="findByUser3" parameterType="User" resultType="User">
select * from t_user where password = #{password} and username = #{username}
</select>

这里很多冗余由于条件不同导致我们要写多次,这里我们想传入什么数据动态匹配条件

MyBatis动态SQL,SQL不像是固定的,可以根据不同的参数信息来动态凭借不同的SQL,以适应不同的需求。

1、创建实体类

1
2
3
4
5
6
7
@Data
public class User{
private Integer id;
private String username;
private String password;
private Integer age;
}

2、创建UserRepository(Mapper.java)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package com.bitzh.repository;

import com.bitzh.entity.User;

/**
* @Auther: oyy0v0
* @Date: 2024/8/6 - 08 - 06 - 19:03
* @Description: com.bitzh.repository
* @version: 1.0
*/
public interface UserRepository {
public User findByUser1(User user);
public User findByUser2(User user);
public User findByUser3(User user);
}

3、Mapper.xml

1
2
3
4
5
6
7
8
9
<?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.bitzh.repository.UserRepository">
<select id="findByUser" parameterType="com.bitzh.entity.User" resultType="com.bitzh.entity.User">
select * from t_user where
id =#{id} and username = #{username} and password = #{password} and age = #{age}
</select>
</mapper>

4、config.xml中注册

1
<mapper resource="com/bitzh/repository/UserRepository.xml"></mapper>

5、测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
package com.bitzh.test;

import com.bitzh.entity.MyClass;
import com.bitzh.entity.User;
import com.bitzh.repository.MyClassRepository;
import com.bitzh.repository.UserRepository;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.InputStream;

/**
* @Auther: oyy0v0
* @Date: 2024/8/5 - 08 - 05 - 21:50
* @Description: com.bitzh.test
* @version: 1.0
*/
public class Test7 {
//这是一个main方法,是程序的入口
public static void main(String[] args) {
InputStream inputStream = Test3.class.getClassLoader().getResourceAsStream("config.xml");
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(inputStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
UserRepository userRepository = sqlSession.getMapper(UserRepository.class);
User user = new User();
// user.setId(2);
user.setPassword("300");
user.setUsername("李四");
user.setAge(6);
User user1 = userRepository.findByUser1(user);
System.out.println(user1);

}
}

动态SQL

  • if
  • where where就是判断如果where和and中间什么都没就会自动删除and。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?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.bitzh.repository.UserRepository">
<select id="findByUser1" parameterType="com.bitzh.entity.User" resultType="com.bitzh.entity.User">
select * from t_user
<where>
<if test="id!=null">
id =#{id}
</if>
<if test="username != null">
and username = #{username}
</if>
<if test="password != null">
and password = #{password}
</if>
<if test="age != null">
and age = #{age}
</if>
</where>
</select>
</mapper>
  • choose,when

这个类似于switch case

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<?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.bitzh.repository.UserRepository">
<select id="findByUser1" parameterType="com.bitzh.entity.User" resultType="com.bitzh.entity.User">
select * from t_user
<where>
<choose>
<when test="id!=null">
id =#{id}
</when>
<when test="username != null">
and username = #{username}
</when>
<when test="password != null">
and password = #{password}
</when>
<when test="age != null">
and age = #{age}
</when>
</choose>

</where>
</select>
</mapper>
  • trim标签

    通过设置prefix和suffix参数来完成使用的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?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.bitzh.repository.UserRepository">
<select id="findByUser1" parameterType="com.bitzh.entity.User" resultType="com.bitzh.entity.User">
select * from t_user
<trim prefix="where" prefixOverrides="and">
<if test="id!=null">
id =#{id}
</if>
<if test="username != null">
and username = #{username}
</if>
<if test="password != null">
and password = #{password}
</if>
<if test="age != null">
and age = #{age}
</if>
</trim>
</select>

</mapper>
  • set

set标签用于Update操作,会自动根据参数来选择生成sql语句。

mapper.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
package com.bitzh.repository;

import com.bitzh.entity.User;

/**
* @Auther: oyy0v0
* @Date: 2024/8/6 - 08 - 06 - 19:03
* @Description: com.bitzh.repository
* @version: 1.0
*/
public interface UserRepository {
public int update(User user);
}

mapper.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<update id="update" parameterType="com.bitzh.entity.User">
update t_user
<set>
<if test="username != null">
username = #{username}
</if>
<if test="password != null">
,password = #{password}
</if>
<if test="age != null">
, age = #{age}
</if>
</set>
where id = #{id}
</update>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
package com.bitzh.test;

import com.bitzh.entity.MyClass;
import com.bitzh.entity.User;
import com.bitzh.repository.MyClassRepository;
import com.bitzh.repository.UserRepository;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.InputStream;

/**
* @Auther: oyy0v0
* @Date: 2024/8/5 - 08 - 05 - 21:50
* @Description: com.bitzh.test
* @version: 1.0
*/
public class Test7 {
//这是一个main方法,是程序的入口
public static void main(String[] args) {
InputStream inputStream = Test3.class.getClassLoader().getResourceAsStream("config.xml");
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(inputStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
UserRepository userRepository = sqlSession.getMapper(UserRepository.class);
User user = new User();
// user.setId(2);
user.setPassword("300");
user.setUsername("李四");
user.setAge(6);
User user1 = userRepository.findByUser1(user);
User user2 = new User();
user2.setId(2);
user2.setUsername("tom");
user2.setAge(18);
userRepository.update(user2);
sqlSession.commit();

}
}

image-20240807023808260