1.简介
MyBatis-Plus(简称 MP)是一个 MyBatis 的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。
2.入门
源码:https://github.com/zhongyushi-git/mybatis-plus-demo.git
2.1数据库准备
使用mysql数据库创建数据,执行脚本在根目录下的sql目录下
2.2环境搭建
1)新建一个SpringBoot的项目,导入需要的坐标
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--mysql数据库依赖-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.9</version>
</dependency>
<!--lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.8</version>
</dependency>
2)yml配置
#数据源配置
spring:
datasource:
#使用阿里巴巴的druid
type: com.alibaba.druid.pool.DruidDataSource
#配置数据库的路径和用户名密码
url: jdbc:mysql://127.0.0.1:3306/mybatisplus?useUnicode=true&characterEncoding=UTF-8&serverTimezone=CTT&zeroDateTimeBehavior=convertToNull&useSSL=false&allowMultiQueries=true
username: root
password: zys123456
2.3引入mybatis-plus开发
1)导入依赖
<!--mybatis-plus-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.0</version>
</dependency>
2)创建实体类
@Data
public class User {
private Long id;
private String name;
private Integer age;
private String email;
}
3)创建dao继承BaseMapper
package com.zys.mybatisplusdemo.dao;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.zys.mybatisplusdemo.entity.User;
public interface UserDao extends BaseMapper<User> {
}
4)在启动类上加mapper扫描
@SpringBootApplication
@MapperScan("com.zys.mybatisplusdemo.dao")
public class MybatisPlusDemoApplication {
public static void main(String[] args) {
SpringApplication.run(MybatisPlusDemoApplication.class, args);
}
}
5)创建controller
@RestController
@RequestMapping("/users")
public class UserController {
@Autowired
private UserDao userDao;
@GetMapping("/list")
public List<User> userList(){
List<User> users = userDao.selectList(null);
return users;
}
}
为了演示方便,这里省略了service的部分而直接调用了dao层,具体见源码。
如果添加了mapper.xml,那么需要配置xml的位置,否则会出现无法绑定。
mybatis-plus.mapperLocations=classpath*:mapper/*.xml
6)测试
启动项目,访问http://localhost:8080/users/list即可看到所有的数据。
3.常用注解
3.1@TableName
其用来将实体对象与数据库表名进行对应。当实体名与数据库表名不一致时使用。
3.2@TableId
其是主键注解,指明是主键,默认把id作为主键。属性type用来指定类型:
1)IdType.AUTO是自动增长;
2)IdType.ASSIGN_UUID是String类型的uuid
3)IdType.INPUT是根据用户的输入作为主键
3.3@TableField
其是表的其他字段注解。属性exist用来指明是否是数据库的字段,值为false时不映射数据库表字段。详细的介绍见后续章节,这里的说明已供使用。
3.4注解开发
1)首先将数据库中表名改为t_user,然后实体User加上注解@TableName
@Data
@TableName(value = "t_user")
public class User {
......
}
启动项目,访问http://localhost:8080/users/list可以正常返回数据。
2)将数据库中表t_user的字段id改为t_id,然后修改实体User的属性id并设置自动增长
@Data
@TableName(value = "t_user")
public class User {
//指定自动增长
@TableId(value = "t_id",type = IdType.AUTO)
private Long id;
......
}
3)将数据表t_user的字段name改为t_name,然后修改实体User的属性name
@TableField(value = "t_name")
private String name;
4)在实体User上添加一个属性,设置不作为数据库的字段
//不映射数据库表字段
@TableField(exist = false)
private String aaa;
启动项目,同上进行访问,数据正常返回。在实际开发过程中,可根据需求使用注解。
4.条件构造器
方法 | 说明 | 示例 |
eq | 等于 |
|
allEq | 全等于 |
|
ne | 不等于 |
|
gt | 大于 |
|
ge | 大于等于 |
|
lt | 小于 |
|
le | 小于等于 |
|
between | BETWEEN 值1 AND 值2 |
|
notBetween | NOT BETWEEN 值1 AND 值2 |
|
like | LIKE '%值%' |
|
notLike | NOT LIKE '%值%' |
|
likeLeft | LIKE '%值' |
|
likeRight | LIKE '值%' |
|
isNull | 字段为null |
|
isNotNull | 字段不为null |
|
in | 同数据库in |
|
notIn | 同数据库not in |
|
inSql | 相当于子查询和in |
|
notInSql | 相当于子查询和not in |
|
groupBy | 同数据库group by |
|
orderBy/orderByDesc | 同数据库order by 字段/order by 字段 desc |
|
having | 同数据库having |
|
or/and | 同数据库or/and |
|
netsted | 正常嵌套 不带 AND 或者 OR |
|
apply | 字符串拼接 |
|
last | 拼接在最后,谨慎使用 |
|
exists/notExists | 拼接sql |
|
select | 指定要查询的字段 |
|
set | 全局修改 |
|
5.CRUD操作
只进行简单的介绍,具体需求请自行开发,都是在这个基础上进行的。需要说明的是,下面的增加和修改操作,只会根据对象中存在不为null的属性来操作数据,当数据为null时不会改变数据库中的数据。
5.1添加insert
@PostMapping("/")
public String save(User user){
int count = userDao.insert(user);
if(count!=0){
return "添加成功";
}else{
return "添加失败";
}
}
5.2删除delete
根据主键删除
@DeleteMapping("/{id}")
public String delete(@PathVariable("id")long id){
int count = userDao.deleteById(id);
if(count!=0){
return "删除成功";
}else{
return "删除失败";
}
}
5.3修改update
根据id进行修改
@PutMapping("/")
public String update(User user){
int count = userDao.updateById(user);
if(count!=0){
return "修改成功";
}else{
return "修改失败";
}
}
5.4简单查询
5.4.1selectList
在入门时,controller中设置的查询条件是null,实际上里面需要传递一个QueryWrapper<T>类型的对象,调用dao的selectList(),此对象中才有上面的那些方法。
1)查询年龄大于等于24的信息
@GetMapping("/list")
public List<User> userList(){
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
//设置查询条件
queryWrapper.ge("age",24);//查询年龄大于等于24的信息
List<User> users = userDao.selectList(queryWrapper);
return users;
}
2)查询名字中含有‘o’的信息
queryWrapper.like("name","o");
5.4.2selectById
根据主键查询
@GetMapping("/{id}")
public User selectById(@PathVariable("id")long id){
return userDao.selectById(id);
}
5.4.3selectCount
查询符合条件的条数,一般和selectList结合使用。
@GetMapping("/list")
public Map<String,Object> userList(){
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
//设置查询条件
queryWrapper.like("name","o");
List<User> users = userDao.selectList(queryWrapper);
Integer integer = userDao.selectCount(queryWrapper);
Map<String,Object> map=new HashMap<>();
map.put("data",users);
map.put("total",integer);
return map;
}
5.5分页查询
5.5.1分页插件配置
新建一个类配置其分页
package com.zys.mybatisplusdemo.config;
import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
import com.baomidou.mybatisplus.extension.plugins.pagination.optimize.JsqlParserCountOptimize;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.annotation.EnableTransactionManagement;
/**
* @Aauthor yushizhong
* @Date 2020/5/17 16:19
* @Dec MybatisPlus分页配置
*/
@EnableTransactionManagement
@Configuration
@MapperScan("com.zys.mybatisplusdemo.dao")
public class MybatisPlusConfig {
@Bean
public PaginationInterceptor paginationInterceptor() {
PaginationInterceptor paginationInterceptor = new PaginationInterceptor();
return paginationInterceptor;
}
}
5.5.2单表分页查询
@GetMapping("/list")
public IPage<User> userList(Integer curr,Integer limit){
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
//设置分页,默认值是1,10
IPage<User> page=new Page<>(curr,limit);
IPage<User> user = userDao.selectPage(page, queryWrapper);
return user;
}
5.5.3单表自定义分页查询
有时使用默认的分页查询无法实现需要的功能时,可以自定义分页查询。
先分析一下其自带的分页的方法,打开源码,看到接口中的selectPage方法:
<E extends com.baomidou.mybatisplus.core.metadata.IPage<T>> E selectPage(E page,
@org.apache.ibatis.annotations.Param("ew") com.baomidou.mybatisplus.core.conditions.Wrapper<T> queryWrapper);
那么自定义也就是模仿其写法,步骤如下:
1)在dao的接口中定义方法
IPage<User> selectPageList(IPage<User> page, @Param(Constants.WRAPPER) QueryWrapper<User> queryWrapper);
对第二个参数queryWrapper使用了@Param注解起别名,其名称使用的是常量的值(实际值是ew),常量的定义也是由官方定义好的,截图如下:
2)在xml中编写sql
<select id="selectPageList" resultType="com.zys.mybatisplusdemo.entity.User">
select * from user ${ew.customSqlSegment}
</select>
那么后面的条件就直接使用"${ew.customSqlSegment}"进行代替了,它会根据设置的条件去查询。
5.5.4多表自定义分页查询
多表分页和单表的分页原来是一样的道理。现假设有两个表,t_student(学生表)和t_clazz(班级表)
1)先创建两个表
CREATE TABLE `clazz` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(50) DEFAULT NULL COMMENT '班级名称',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;
CREATE TABLE `student` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(20) DEFAULT NULL COMMENT '学生姓名',
`clazzId` int(11) DEFAULT NULL COMMENT '班级id',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8;
insert into clazz values(1,'计算机1班'),(2,'计算机2班'),(3,'计算机3班');
insert into student values(null,'赵敏',1),(null,'张明',3),(null,'李慧',3),(null,'赵美美',2),(null,'张峰',2),(null,'孙强',2);
2)创建学生实体类
@Data
@TableName(value = "user")
public class Student {
@TableId(value = "id",type = IdType.AUTO)
private Long id;
@TableField(value = "name")
private String name;
@TableField(value = "clazzId")
private Integer clazzId;
@TableField(exist = false)
private String clazzName;
}
3)创建controller接口
@GetMapping("/list")
public JSONObject getList(Integer curr, Integer limit) {
QueryWrapper<Student> queryWrapper = new QueryWrapper<>();
queryWrapper.like("t1.name", "张");
IPage<Student> page = new Page<>(curr, limit);
IPage<Student> stu = studentDao.selectPageList(page, queryWrapper);
JSONObject jsonObject = new JSONObject();
jsonObject.put("data", stu.getRecords());
jsonObject.put("total", stu.getTotal());
return jsonObject;
}
4)在dao接口定义方法
IPage<Student> selectPageList(IPage<Student> page, @Param(Constants.WRAPPER) QueryWrapper<Student> queryWrapper);
5)在xml编写sql
<select id="selectPageList" resultType="com.zys.mybatisplusdemo.entity.Student">
select t1.*,t2.name "clazzName" from student t1
left join clazz t2 on t1.clazzId = t2.id
${ew.customSqlSegment}
</select>
6)调用此接口,数据可以正常查询。执行日志如下:
当然,对于多表查询,如果使用默认的条件查询不能满足要求,可以把QueryMapper换成Mmap,那么在xml中使用对应的参数查询即可。 不过这种方式有些麻烦,但是可以实现更为复杂的需求
dao接口的方法:
IPage<Student> selectPageList2(IPage<Student> page, @Param(Constants.WRAPPER)Map<String, Object> map);
xml的sql:
<select id="selectPageList2" resultType="com.zys.mybatisplusdemo.entity.Student">
select t1.*, t2.name "clazzName"
from student t1
left join clazz t2 on t1.clazzId = t2.id
<where>
<if test="ew.name != null and ew.name != ''">
and t1.name like concat('%',#{ew.name},'%')
</if>
</where>
</select>
需要注意的是,在if标签中也需要带ew,否则会报错。
6.代码生成器
代码生成器自动生成包及需要的类名,节省开发的时间。前提是数据库中表已经建好,原因是它根据数据库表进行创建的。
首先导入依赖
<!--mybatis-plus代码生成器-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>3.4.0</version>
</dependency>
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity-engine-core</artifactId>
<version>2.2</version>
</dependency>
创建生成器类,然后执行main方法
package com.zys.mybatisplusdemo.config;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.InjectionConfig;
import com.baomidou.mybatisplus.generator.config.*;
import com.baomidou.mybatisplus.generator.config.po.TableInfo;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;
import java.util.ArrayList;
import java.util.List;
/**
* @Aauthor yushizhong
* @Date 2020/5/17 16:45
* @Dec 代码生成器
*/
public class CodeGenerator {
public static void main(String[] args) {
// 代码生成器
AutoGenerator map = new AutoGenerator();
// 全局配置
GlobalConfig globalConfig = new GlobalConfig();
//配置生成文件的输出目录
globalConfig.setOutputDir(System.getProperty("user.dir") + "/src/main/java");
//设置开发人员名称
globalConfig.setAuthor("yushizhong");
//是否打开输出目录
globalConfig.setOpen(false);
//mapper 命名方式
globalConfig.setMapperName("%sDao");
//service 命名方式
globalConfig.setServiceName("%sService");
map.setGlobalConfig(globalConfig);
//数据源配置
DataSourceConfig dataSourceConfig = new DataSourceConfig();
//数据库的路径
dataSourceConfig.setUrl("jdbc:mysql://localhost:3306/test?useUnicode=true&useSSL=false&characterEncoding=utf8&serverTimezone=CTT");
//数据库驱动名称
dataSourceConfig.setDriverName("com.mysql.jdbc.Driver");
//数据库的登录用户名
dataSourceConfig.setUsername("root");
//数据库的登录密码
dataSourceConfig.setPassword("123456");
map.setDataSource(dataSourceConfig);
// 包配置
PackageConfig pc = new PackageConfig();
//设置父包名
pc.setParent("com.zys.mybatisplusdemo");
pc.setMapper("dao");
map.setPackageInfo(pc);
// 自定义配置
InjectionConfig cfg = new InjectionConfig() {
@Override
public void initMap() {
}
};
String templatePath = "/templates/mapper.xml.vm";
// 自定义输出配置
List<FileOutConfig> focList = new ArrayList<>();
// 自定义配置会被优先输出
focList.add(new FileOutConfig(templatePath) {
@Override
public String outputFile(TableInfo tableInfo) {
//设置xml的输出路径
return System.getProperty("user.dir") + "/src/main/resources/mapper/" + tableInfo.getEntityName() + "Mapper" + StringPool.DOT_XML;
}
});
cfg.setFileOutConfigList(focList);
map.setCfg(cfg);
// 配置模板
TemplateConfig templateConfig = new TemplateConfig();
//在代码总不生成xml
templateConfig.setXml(null);
map.setTemplate(templateConfig);
// 策略配置
StrategyConfig strategy = new StrategyConfig();
//数据库表映射到实体的命名策略:把下划线变成大写
strategy.setNaming(NamingStrategy.underline_to_camel);
//数据库表字段映射到实体的命名策略:把下划线变成大写
strategy.setColumnNaming(NamingStrategy.underline_to_camel);
//是否使用lombok
strategy.setEntityLombokModel(true);
strategy.setRestControllerStyle(true);
// 写于父类中的公共字段
strategy.setSuperEntityColumns("id");
strategy.setControllerMappingHyphenStyle(true);
//表前缀
strategy.setTablePrefix(pc.getModuleName() + "_");
map.setStrategy(strategy);
//执行
map.execute();
}
}
7.实现缓存
对于有些查询比较频繁的数据,可以放到缓存中,这里就以redis为例。mybatis-plus的缓存和mybatis的缓存实现原理类似,也有区别,mybatis的缓存实现请参考
7.1实战演练
1)导入redis的依赖,配置redis数据库参数(见源码)
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
2)在配置文件中开启缓存
mybatis-plus:
configuration:
#开启缓存
cache-enabled: true
如果不开启,那么缓存就不会生效。
3)获取spring创建的工厂
package com.zys.mybatisplusdemo.util;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.Configuration;
/**
* @author zhongyushi
* @date 2020/9/16 0016
* @dec 获取spring创建的工厂
*/
@Configuration
public class ApplicationContextUtil implements ApplicationContextAware {
private static ApplicationContext applicationContext;
//把非spring创建好的工厂赋值给applicationContext,applicationContext在这个应用中是唯一的
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
//此创建好工厂后再获取对象
public static Object getBean(String beanName){
return applicationContext.getBean(beanName);
}
}
4)创建redis缓存配置类,实现Cache,重写方法
package com.zys.mybatisplusdemo.config;
import com.zys.mybatisplusdemo.util.ApplicationContextUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.cache.Cache;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
/**
* @author zhongyushi
* @date 2020/9/28 0028
* @dec MybatisPlus缓存配置,使用redis作为缓存服务器
*/
@Slf4j
public class MybatisPlusCache implements Cache {
// 读写锁
private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock(true);
//这里使用了redis缓存,使用springboot自动注入
private RedisTemplate<String, Object> redisTemplate;
private String id;
//是mybatis必须要求的,必写。此id是xml中的namespace的值
public MybatisPlusCache(final String id) {
if (id == null) {
throw new IllegalArgumentException("未获取到缓存实例id");
}
this.id = id;
}
//返回cache的唯一名称
@Override
public String getId() {
return this.id;
}
//缓存存值
@Override
public void putObject(Object key, Object value) {
//id是namespace的值,key是方法名,value是查询的结果
getRedisTemplate().opsForHash().put(id, key.toString(), value);
}
//缓存取值
@Override
public Object getObject(Object key) {
return getRedisTemplate().opsForHash().get(id, key.toString());
}
//mybatis保留方法
@Override
public Object removeObject(Object key) {
return null;
}
//清空缓存,在增删改时会自动调用
@Override
public void clear() {
getRedisTemplate().delete(id);
}
@Override
public int getSize() {
return getRedisTemplate().opsForHash().size(id).intValue();
}
@Override
public ReadWriteLock getReadWriteLock() {
return this.readWriteLock;
}
//获取RedisTemplate,不能通过注入的方式,原因是此类是由mybatis实例化的
private RedisTemplate getRedisTemplate() {
//从上下文中获取redisTemplate
RedisTemplate redisTemplate = (RedisTemplate) ApplicationContextUtil.getBean("redisTemplate");
//设置key是string类型的序列
redisTemplate.setKeySerializer(new StringRedisSerializer());
//设置hashKey是string类型的序列
redisTemplate.setHashKeySerializer(new StringRedisSerializer());
return redisTemplate;
}
}
在这个类中,分别重写了缓存设置、获取和删除的方法,把数据放到redis中。但是在此类中无法直接注入RedisTemplate,此类是由mybatis实例化的,不是由工厂实例化的。但是可以通过applicationContext来获取。
4)开启缓存
在UserDao接口上添加注解,指定缓存的配置类
@CacheNamespace(implementation= MybatisPlusCache.class,eviction=MybatisPlusCache.class)
public interface UserDao extends BaseMapper<User> {
...
}
5)测试。启动项目,第一次访问http://localhost:8080/users/list,查看控制台,会发现打印了sql的执行日志,多次访问此路径,它就从redis中获取数据了,同时可以在redis中看到此缓存信息。
对于增删改操作,都会清空缓存。因此作为缓存的数据一般是频繁查询,很少修改的信息。
7.2注意事项
通过对比mybatis的缓存可以发现,这里指定缓存的配置类是在dao接口上用注解配置的,而mybatis是在xml中配置的。实际上,也可以在xml中配置,但是二者不可兼得。
1)在dao接口中配置,那么只能缓存使用mybatis-plus查询出来的数据。也就是说,在xml中编写的查询语句所查询的结果是不会存入缓存的。
2)在xml中配置,那么只能缓存xml中编写的查询语句所查询的结果,使用mybatis-plus查询出来的数据是不会存入缓存的。
xml中配置如下:
<cache type="com.zys.mybatisplusdemo.config.MybatisPlusCache"/>
说明:使用mybatis-plus查询出来的数据指的是不编写sql,直接调用其内部已经编写好的查询方法。
8.@TableField注解详细说明
8.1说明
属性名 | 描述 |
value | 映射数据库的字段名 |
update | 预处理set进行自定义注入(结合fill) |
condition | 预处理where进行自定义条件查询(不常用) |
exist | 是否映射数据库的字段(默认是true,值为false则不映射) |
fill | 字段填充,需结合FieldFill使用 |
对于value和exist在前面已经介绍,在此不再赘述。
8.2 update-修改时操作
1)注入当前的时间
假如在每次更新数据时都需要把时间改成当前操作的时间,那么可以对其进行配置为数据库的时间:
@TableField(value = "update_time", update = "now()",fill = FieldFill.UPDATE)
private Date updateTime;
需要结合fill使用,将其设置为更新时更新数据。设置后需调用mybatisplus自带的修改方法update(),否则不生效
输入的SQL如下:
UPDATE 表 SET update_time=now() WHERE 条件
2)修改变量的值
在每次修改时需要记录修改次数时,可以使用下面的方式。
@TableField(value = "count",update = "%s+1", fill = FieldFill.UPDATE)
private Integer count;
其中"%s"是填充的字段,在这里是count,输出的SQL如下:
UPDATE 表 SET count=count+1 WHERE 条件
不过需要注意的是,在使用时,count在数据库中必须有值,为空时不会修改其值。
8.3 fill与FieldFill
对数据进行自动填充操作。上一小节结合update属性进行了说明。本小节不结合update属性进行添加或修改。
若需要在添加时插入添加时间,修改时同步修改时间。可对对象的字段进行设置,使用fill:
@TableField(value = "create_time", fill = FieldFill.INSERT)
private Date createTime;
@TableField(value = "update_time", fill = FieldFill.UPDATE)
private Date updateTime;
还需要添加一个配置类实现MetaObjectHandler接口,重写两个方法
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.context.annotation.Configuration;
import java.util.Date;
@Configuration
public class MyMetaObjectHandler implements MetaObjectHandler {
@Override
public void insertFill(MetaObject metaObject) {
this.setFieldValByName("createTime", new Date(), metaObject);
}
@Override
public void updateFill(MetaObject metaObject) {
this.setFieldValByName("updateTime", new Date(), metaObject);
}
}
可以看出在配置类中对方法重写时,指定了字段名和时间,从而实现自定义插入时间。其他的公共字段也可以使用这种方式。
这种方式显而易见有很大的局限性,对时间的两个字段进行了限定,那么对象的这两个字段就固定了。可根据实际需求选择是否使用这种方式。
8.4记录操作人信息
在每次新增时将插入时间,插入人,修改时间和修改人都赋值,修改时将修改时间和修改人进行更新。那么需要在上述的基础上配置登录用户的信息,若有用户对象如下
import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;
import lombok.experimental.Accessors;
import java.util.Date;
@Data
@TableName(value = "t_user")
@Accessors(chain = true)
public class User1 {
@TableId(type = IdType.AUTO)
private Long id;
private String name;
private Integer age;
private String email;
@TableField(value = "insert_by", fill = FieldFill.INSERT)
private String insertBy;
@TableField(value = "update_by", fill = FieldFill.INSERT_UPDATE)
private String updateBy;
@TableField(value = "insert_time", fill = FieldFill.INSERT)
private Date insertTime;
@TableField(value = "update_time", fill = FieldFill.INSERT_UPDATE)
private Date updateTime;
}
更新人和更新时间都需要设置为"INSERT_UPDATE"才能在新增时同步插入值,若不需要插入,则设置为"UPDATE"即可。那么需要配置如下:
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.context.annotation.Configuration;
import java.util.Date;
@Configuration
public class MyMetaObjectHandler implements MetaObjectHandler {
//模拟获取登录用户信息
private String loginName="22222";
@Override
public void insertFill(MetaObject metaObject) {
this.setFieldValByName("insertTime", new Date(), metaObject);
this.setFieldValByName("updateTime", new Date(), metaObject);
this.setFieldValByName("insertBy", loginName, metaObject);
this.setFieldValByName("updateBy", loginName, metaObject);
}
@Override
public void updateFill(MetaObject metaObject) {
this.setFieldValByName("updateTime", new Date(), metaObject);
this.setFieldValByName("updateBy", loginName, metaObject);
}
}
上述就并未按照上一章节的字段进行说明,使用了新的基础字段,不过在项目中,这些字段都会在重要的表中进行统一,那么这种方式也符合了需求。