创建Gradle项目
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
|
plugins {
id 'org.springframework.boot' version '2.5.6'
id "com.thinkimi.gradle.MybatisGenerator" version "2.4"
}
apply plugin: 'java'
apply plugin: 'io.spring.dependency-management'
group 'io.github.qinry'
version '1.0-SNAPSHOT'
sourceCompatibility = JavaVersion.VERSION_11
repositories {
mavenCentral()
}
dependencies {
implementation 'org.mybatis.spring.boot:mybatis-spring-boot-starter:2.2.0'
runtimeOnly 'mysql:mysql-connector-java'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
}
test {
useJUnitPlatform()
}
|
编写 generatorConfig.xml
在项目根路径下创建generatorConfig.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
|
<!DOCTYPE generatorConfiguration PUBLIC
"-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
"http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration>
<context id="Mysql" targetRuntime="Mybatis3">
<plugin type="org.mybatis.generator.plugins.SerializablePlugin"></plugin>
<plugin type="org.mybatis.generator.plugins.UnmergeableXmlMappersPlugin"></plugin>
<plugin type="org.mybatis.generator.plugins.FluentBuilderMethodsPlugin"></plugin>
<plugin type="org.mybatis.generator.plugins.ToStringPlugin"></plugin>
<!-- 生成的代码没有注释 -->
<commentGenerator>
<property name="suppressAllComments" value="true" />
</commentGenerator>
<jdbcConnection driverClass="com.mysql.cj.jdbc.Driver"
connectionURL="jdbc:mysql://localhost:3306/testdb"
userId="springuser"
password="123456"/>
<!-- 不强制使用BigDecimal字段,使数据库为NUMBERIC或DECIMAL字段被整型类型替换,会更易于使用 -->
<javaTypeResolver>
<property name="forceBigDecimals" value="false" />
</javaTypeResolver>
<javaModelGenerator targetPackage="com.owk.domain" targetProject="src/main/java">
<property name="trimStrings" value="true" />
</javaModelGenerator>
<sqlMapGenerator targetPackage="com.owk.mapper" targetProject="src/main/resources"/>
<javaClientGenerator type="XMLMAPPER" targetPackage="com.owk.mapper" targetProject="src/main/java"/>
<table tableName="student" domainObjectName="Student" >
<generatedKey column="ID" sqlStatement="MySql" identity="true" />
</table>
<table tableName="grade" domainObjectName="Grade">
<generatedKey column="ID" sqlStatement="MySql" identity="true"/>
</table>
</context>
</generatorConfiguration>
|
org.mybatis.generator.plugins.SerializablePlugin
生成的模型类实现Serializable
接口
org.mybatis.generator.plugins.UnmergeableXmlMappersPlugin
产生的影响是,如果生成xml映射文件的文件名已存在,则不会合并已存在的内容。这个插件按需要添加。总之就是会覆盖之前的内容
org.mybatis.generator.plugins.FluentBuilderMethodsPlugin
生成的模型类准备流畅建造者模式,在测试用例可查看到使用
org.mybatis.generator.plugins.ToStringPlugin
为模型创建 toString()
方法
<jdbcConnection>
用于连接数据库,代码生成插件是按照数据库表生成模型、映射器和 xml
<javaModelGenerator>
决定生成Java模型类的位置,String类型字段使不实用 trim()
方法
<sqlMapGenerator>
决定生成映射器xml文件的位置
<javaClientGenerator>
决定生成映射器接口的位置
创建数据库表
这个插件是依赖于数据库生成代码的。所以要提前建好表格
1
2
3
4
5
6
7
8
9
10
11
12
|
create table student(
id bigint not null auto_increment,
stu_name varchar(32) default null,
grade_id bigint default null,
primary key (id)
)engine=innodb default charset=utf8mb4;
create table grade(
id bigint not null auto_increment,
grade_name varchar(32) default null,
primary key (id)
)engine=innodb default charset=utf8mb4;
|
执行生成任务
保证包 com.owk
提前创建好,这个插件默认配置不会创建层级超过一的目录。有IDE支持就更加方便。
生成代码如下:
src/main
├── java
│ └── com
│ └── owk
│ ├── mapper
│ │ ├── GradeMapper.java
│ │ └── StudentMapper.java
│ └── domain
│ ├── Grade.java
│ ├── GradeExample.java
│ ├── Student.java
│ └── StudentExample.java
└── resources
├── com
│ └── owk
│ └── mapper
│ ├── GradeMapper.xml
│ └── StudentMapper.xml
设置项目属性
1
2
3
4
5
6
7
8
9
10
11
|
spring:
datasource:
url: jdbc:mysql://localhost:3306/testdb?serverTimezone=UTC&useUnicode=true&characterEncoding=UTF-8
driver-class-name: com.mysql.cj.jdbc.Driver
username: springuser
password: 123456
mybatis:
config-location: classpath:mybatis-config.xml
logging:
level:
com.owk.mapper: trace
|
设置数据源还有设置mybatis配置文件位置。
编写mybatis-config.xml
1
2
3
4
5
6
7
8
9
10
11
12
|
<?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>
<settings>
<setting name="mapUnderscoreToCamelCase" value="true"/>
<setting name="lazyLoadingEnabled" value="true"/>
<setting name="aggressiveLazyLoading" value="false" />
<setting name="logImpl" value="SLF4J" />
</settings>
</configuration>
|
设置mybatis,开启数据库字段的下划线写法映射为驼峰写法。开启延迟加载,取消积极加载。指定映射器路径。
使用生成的代码
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
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
|
/**
* 测试前请先清空表数据 <code>truncate student</code>
*/
@SpringBootTest
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class StudentMapperTests {
@Resource
private StudentMapper studentMapper;
private List<Long> ids;
@BeforeEach
void setUp() {
System.out.println("\033[0;92m****************测试开始******************\033[0m");
System.out.println("\033[0;92m***************填充三行数据**************\033[0m");
studentMapper.insert(new Student().withStuName("张三").withGradeId(1L));
studentMapper.insert(new Student().withStuName("李四").withGradeId(2L));
studentMapper.insert(new Student().withStuName("王五").withGradeId(3L));
ids = studentMapper.selectByExample(null).stream().map(Student::getId).collect(Collectors.toList());
}
/**
* 增
*/
@Test
@Order(1)
void create() {
System.out.println("\033[0;92m***************插入两行行数据**************\033[0m");
// 使用流畅建造者,动态插入字段值
studentMapper.insertSelective(new Student().withStuName("赵六").withGradeId(1L)); // [1]
// 除了主键外,所有字段值插入
studentMapper.insert(new Student().withStuName("武七").withGradeId(2L)); // [2]
StudentExample example = new StudentExample();
StudentExample.Criteria criteria = example.createCriteria();
criteria.andStuNameIn(List.of("赵六", "武七"));
System.out.println("\033[0;92m*****************查询刚插入的数据****************\033[0m");
studentMapper.selectByExample(example);
}
/**
* 查
*/
@Test
@Order(2)
void read() {
System.out.println("\033[0;92m*************查询学生姓名包含李*************\033[0m");
StudentExample example = new StudentExample();
StudentExample.Criteria criteria = example.createCriteria();
criteria.andStuNameLike("%李%");
List<Student> students = studentMapper.selectByExample(example); // [3]
List<Long> ids = students.stream().map(Student::getId).collect(Collectors.toList());
ids.forEach(id -> {
System.out.println("\033[0;92m********查询主键"+id+"的数据********\033[0m");
studentMapper.selectByPrimaryKey(id); // [4]
});
}
/**
* 改
*/
@Test
@Order(3)
void update() {
System.out.println("\033[0;92m*******************更新id为"+ids.get(0)+"********************\033[0m");
// 动态更新字段值
studentMapper.updateByPrimaryKeySelective(new Student().withId(ids.get(0)).withStuName("杨开").withGradeId(2L)); // [5]
// 更新所有字段值
studentMapper.updateByPrimaryKey(new Student().withId(ids.get(1)).withStuName("苏颜").withGradeId(3L)); // [6]
StudentExample example = new StudentExample();
StudentExample.Criteria criteria = example.createCriteria(); //
criteria.andStuNameLike("%王%");
studentMapper.updateByExampleSelective(new Student().withGradeId(1L), example); // [7]
Student student = studentMapper.selectByPrimaryKey(ids.get(2));
studentMapper.updateByExample(student.withStuName("夏霓裳"), example); // [8]
System.out.println("\033[0;92m*****************查询更新后的数据****************\033[0m");
studentMapper.selectByExample(null);
}
/**
* 删
*/
@Test
@Order(4)
void delete() {
List<Student> students = studentMapper.selectByExample(null);
List<Long> ids = students.stream().map(Student::getId).collect(Collectors.toList());
System.out.println("\033[0;92m*******************删除主键"+ids.get(0)+"********************\033[0m");
studentMapper.deleteByPrimaryKey(ids.get(0)); // [9]
System.out.println("\033[0;92m*******************删除年级id为3********************\033[0m");
StudentExample example = new StudentExample();
StudentExample.Criteria criteria = example.createCriteria();
criteria.andGradeIdEqualTo(3L);
studentMapper.deleteByExample(example); // [10]
System.out.println("\033[0;92m*****************查询删除后的数据****************\033[0m");
studentMapper.selectByExample(null);
}
@AfterEach
void tearDown() {
System.out.println("\033[0;92m*******************测试结束********************\033[0m");
studentMapper.deleteByExample(null);
}
}
|
这个测试用例,展示了增删改查的使用,条件查询如何创建动态的条件。更多的用法细节可以查看生成映射器接口和xml映射文件。
更多参见官方文档