tk.mybatis的使用

宋正兵 on 2020-10-19

tk.mybatis—集成通用mapper

参考:

https://www.jianshu.com/p/336c71c68a52

https://www.cnblogs.com/alimayun/p/12572350.html

https://www.cnblogs.com/zkm1992/p/10939730.html#autoid-4-0-0

引入依赖

使用版本取决于 Spring Boot 的版本,因为存在兼容性问题,版本需要提前确认好。

1
2
3
4
<dependency>
<groupId>tk.mybatis</groupId>
<artifactId>mapper-spring-boot-starter</artifactId>
<version>2.1.5</version>

增加 mapper 组件扫描配置

vy7abT3cgtJYwf4.png

1
2
import tk.mybatis.spring.annotation.MapperScan;
@MapperScan("com.songzb.demomall.mapper")

创建 dao 层的 base 接口

注意:base 接口一定不要被 Mapper 组件扫描配置给扫描到!

这里实际有问题,没能解决。所以无需创建base接口,直接继承Mapper使用即可。

创建 BaseMapper 继承 3 个 tk.mybatis.mapper 下的接口:

  1. Mapper
  2. IdsMapper
  3. InsertListMapper
1
2
public interface BaseMapper<T> extends Mapper<T>, IdsMapper<T>, InsertListMapper<T> {
}

当用的数据库是 mysql,也可以继承如下的几个接口:

  1. Mapper
  2. MysqlMapper
1
2
public interface BaseMapper<T> extends Mapper<T>, MySqlMapper<T> {
}

创建 dao 层查询接口

创建 dao 层查询接口PmsBrandMapper,继承 dao 层的 base 接口 BaseMapper,泛型为数据库表对应的映射类。

1
2
3
4
5
/**
* Create By songzb on 2020/10/16
*/
public interface PmsBrandMapper extends BaseMapper<PmsBrand> {
}

也可以简单的进行实现,比如直接继承 Mapper 接口

1
2
3
> public interface PmsBrandMapper extends Mapper<PmsBrand> {
> }
>

service 调用 dao 层进行查询

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
@Service
public class PmsBrandServiceImpl implements PmsBrandService {

@Autowired
private PmsBrandMapper pmsBrandMapper;

@Override
public List<PmsBrand> listAllBrand() {
return pmsBrandMapper.selectAll();
}

@Override
public int creatBrand(PmsBrand pmsBrand) {
return pmsBrandMapper.insertSelective(pmsBrand);
}

@Override
public int updateBrand(Long id, PmsBrand pmsBrand) {
pmsBrand.setId(id);
return pmsBrandMapper.updateByPrimaryKeySelective(pmsBrand);
}

@Override
public int deleteBrand(Long id) {
return pmsBrandMapper.deleteByPrimaryKey(id);
}

@Override
public List<PmsBrand> listBrand(int pageNum, int pageSize) {
// select * from pms_brand limit (pageNum-1)*pageSize, pageSize
PageHelper.startPage(pageNum, pageSize);
return pmsBrandMapper.selectAll();
}

@Override
public PmsBrand getBrand(Long id) {
return pmsBrandMapper.selectByPrimaryKey(id);
}
}

实体类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@Data
@Table(name = "pms_brand")
public class PmsBrand {
// 设置主键
@Id
// 主键回填,当写入没有指定 id 时,数据库自增生成一个 id,然后回填到这里
@KeySql(useGeneratedKeys = true)
private Long id;
private String name;
private String firstLetter;
private Integer sort;
private Integer factoryStatus;
private Integer showStatus;
private Integer productCount;
private Integer productCommentCount;
private String logo;
private String bigPic;
private String brandStory;
}

注意事项

1.表名默认使用类名,驼峰转下划线(只对大写字母进行处理),如 TestUser 默认对应的表名为 test_user,

2.表名可以使用 @Table(name = “tableName”) 进行指定,对不符合第一条默认规则的可以通过这种方式指定表名。

3.字段默认和 @Column一样,都会作为表字段,表字段默认为 Java 对象的Field名字驼峰转下划线形式。

4.可以使用 @Column(name = “fieldName”) 指定不符合第 3 条规则的字段名

5.使用 @Transient 注解可以忽略字段,添加该注解的字段不会作为表字段使用。如果你的实体类中包含了不是数据库表中的字段,你需要给这个字段加上 @Transient 注解,这样通用 Mapper 在处理单表操作时就不会将标注的属性当成表字段处理!

6.建议一定是有一个 @Id 注解作为主键的字段,可以有多个 @Id 注解的字段作为联合主键。

7.默认情况下,实体类中如果不存在包含 @Id 注解的字段,所有的字段都会作为主键字段进行使用(这种效率极低)。

8.实体类可以继承使用,可以参考测试代码中的 tk.mybatis.mapper.model.UserLogin2 类。

9.由于基本类型,如 int 作为实体类字段时会有默认值 0 ,而且无法消除,所以实体类中建议不要使用基本类型。

10.@NameStyle 注解,用来配置对象名/字段和表名/字段之间的转换方式,该注解优先于全局配置 style,可选值:
normal:使用实体类名/属性名作为表名/字段名
camelhump:这是默认值,驼峰转换为下划线形式
uppercase:转换为大写
lowercase:转换为小写

基础接口

假设现在有实体类 TestUser:

1
2
3
4
5
6
public class TestUser {
private String id;
private String name;
private String username;
private String password;
}

Insert

1.InsertMapper

接口:InsertMapper

方法:int insert(T record);

说明:保存一个实体,null 的属性也会保存,不会使用数据库默认值

1
2
3
public int insertTestUser(TestUser testUser) {
return testUserMapper.insert(testUser);
}

结果:数据库表中新增一个 testUser

2.InsertSelectiveMapper

接口:InsertSelectiveMapper

方法:int insertSelectiveMapper(T record);

说明:保存一个实体,null 的属性不会保存,会使用数据库默认值

1
2
3
public int insertTestUser(TestUser testUser) {
return testUserMapper.insert(testUser);
}

结果:略

Update

1.UpdateByPrimaryKeyMapper

接口:UpdateByPrimaryKeyMapper

方法:int updateByPrimaryKey(T record);

说明:根据主键更新实体全部字段,null 值会被更新

结果:会把没有属性的值变成空

2.UpdateByPrimaryKeySelectiveMapper

接口:UpdateByPrimaryKeySelectiveMapper

方法:int updateByPrimaryKeySelective(T record);

说明:根据主键更新,属性不为 null 的值

结果:会把没有属性的值变成默认值

Delete

1.DeleteMapper

接口:DeleteMapper

方法:int delete(T record);

说明:根据实体属性作为条件进行删除,查询条件使用等号

1
2
3
4
5
6
public int deleteTestUser() {
TestUser testUser=new TestUser();
//根据属性删除会把所有密码是123456的数据删除
testUser.setPassword("123456");
return testUserMapper.delete(testUser);
}

结果:略

2.DeleteByPrimaryKeyMapper

接口:DeleteByPrimaryKeyMapper

方法:int deleteByPrimaryKey(T record);

说明:根据主键字段进行删除,方法参数必须包含完整的主键属性

结果:略

Select

1.SelectMapper

接口:SelectMapper

方法:List select(T record);

说明:根据实体中的属性值进行查询,查询条件使用等号

1
2
3
4
5
6
public List<TestUser> selectTestUser() {
TestUser testUser=new TestUser();
testUser.setPassword("123456");
testUser.setUsername("lisi");
return testUserMapper.select(testUser);
}

结果:略

2.SelectByPrimaryKeyMapper

接口:SelectByPrimaryKeyMapper

方法:T selectByPrimaryKey(Object key);

说明:根据主键字段进行查询,方法参数必须包含完整的主键属性,查询条件使用等号

结果:根据主键查询,略

3.SelectAllMapper

接口:SelectAllMapper

方法:List selectAll();

说明:查询全部结果,select(null) 方法能达到同样的效果

结果:查询所有,略

4.SelectOneMapper

接口:SelectOneMapper

方法:T selectOne(T record);

说明:根据实体中的属性进行查询,只能有一个返回值,有多个结果是抛出异常,查询条件使用等号

1
2
3
4
5
6
public TestUser selectOneTestUser() {
TestUser testUser=new TestUser();
testUser.setUsername("wangwu");
//结果只能返回一条数据否则会抛出异常
return testUserMapper.selectOne(testUser);
}

结果:查询出 username 为 “wangwu” 的数据

5.SelectCountMapper

接口:SelectCountMapper

方法:int selectCount(T record);

说明:根据实体中的属性查询总数,查询条件使用等号

结果:返回查询个数,略

Example 方法

Select 方法

1.SelectCountMapper

接口:SelectByExampleMapper

方法:List selectByExample(Object example);

说明:根据 Example 条件进行查询,这个查询支持通过 Example 类指定查询列,通过 selectProperties 方法指定查询列

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public List<TestUser> selectExample() {
Example example = new Example(TestUser.class);
//排序方法setOrderByClause("字段名 ASC")DESC降序
example.setOrderByClause("name ASC");
example.createCriteria()
//添加xxx字段等于value条件
.andEqualTo("password","123456")
//模糊查询xxx字段like value条件
.andLike("name","%四%")
//可以自由拼接SQL
//.andCondition("ID = '5f7139ef295d42a3b964c082e0dd838f' ")
//或者可以这么写
.andCondition("ID =","5f7139ef295d42a3b964c082e0dd838f")
;
return testUserMapper.selectByExample(example);
}

实例解析:

mybatis 的逆向工程中会生成实例及实例对应的 example,example 用于添加条件,相当 where 后面的部分
Example example = new Example();
Criteria criteria = example.createCriteria();

方法表

方法 说明
example.setOrderByClause(“字段名 ASC”) 添加升序排列条件,DESC为降序
example.setDistinct(false) 去除重复,boolean型,true为选择不重复的记录。
criteria.andIsNull(“字段”) 添加字段xxx为null的条件
criteria.andIsNotNull(“字段”) 添加字段xxx不为null的条件
criteria.andEqualTo(“字段”,value) 添加xxx字段等于value条件
criteria.andNotEqualTo(“字段”,value) 添加xxx字段不等于value条件
criteria.andGreaterThan(“字段”,value) 添加xxx字段大于value条件
criteria.andGreaterThanOrEqualTo(“字段”,value) 添加xxx字段大于等于value条件
criteria.andLessThan(“字段”,value) 添加xxx字段小于value条件
criteria.andLessThanOrEqualTo(“字段”,value) 添加xxx字段小于等于value条件
criteria.andIn(“字段”,List<?>) 添加xxx字段值在List<?>条件
criteria.andNotIn(“字段”,List<?>) 添加xxx字段值不在List<?>条件
criteria.andLike(“字段”,“%”+value+”%”) 添加xxx字段值为value的模糊查询条件
criteria.andNotLike(“字段”,“%”+value+”%”) 添加xxx字段值不为value的模糊查询条件
criteria.andBetween(value1,value2) 添加xxx字段值在value1和value2之间条件
criteria.andNotBetween(value1,value2) 添加xxx字段值不在value1和value2之间条件
criteria.andCondition(“SQL”) 可以写字符串拼接SQL
criteria.andCondition(“字段 =”,value) 前面可以写SQL后面可以写值

2.SelectCountByExampleMapper

接口:SelectCountByExampleMapper

方法:int selectCountByExample(Object example);

说明:根据Example条件进行查询总数

Update方法

1.UpdateByExampleMapper

接口:UpdateByExampleMapper

方法:int updateByExample(T record, Object example);

说明:根据Example条件更新实体record包含的全部属性,null值会被更新

2.UpdateByExampleSelectiveMapper

接口:UpdateByExampleSelectiveMapper

方法:int updateByExampleSelective(T record, Object example);

说明:根据Example条件更新实体record包含的不是null的属性值

Delete方法

1.DeleteByExampleMapper

接口:DeleteByExampleMapper

方法:int deleteByExample(Object example);

说明:根据Example条件删除数据