前言
项目中有时会用到mybatis的插件,我这里就简单的用插件拦截器实现数据库表中字段创建人,创建时间,更新人,更新时间的默认插入。
注:springboot+mybatis
引入mybatis依赖
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.2.0</version>
</dependency>
实操
1、创建实体类
public class MybatisDO implements Serializable {
private Long id;
private String name;
private String version;
private String createBy;
private String updateBy;
private Date createTime;
private Date updateTime;
public MybatisDO() {
}
public MybatisDO(Long id, String name, String version, String createBy, String updateBy, Date createTime, Date updateTime) {
this.id = id;
this.name = name;
this.version = version;
this.createBy = createBy;
this.updateBy = updateBy;
this.createTime = createTime;
this.updateTime = updateTime;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getVersion() {
return version;
}
public void setVersion(String version) {
this.version = version;
}
public String getCreateBy() {
return createBy;
}
public void setCreateBy(String createBy) {
this.createBy = createBy;
}
public String getUpdateBy() {
return updateBy;
}
public void setUpdateBy(String updateBy) {
this.updateBy = updateBy;
}
public Date getCreateTime() {
return createTime;
}
public void setCreateTime(Date createTime) {
this.createTime = createTime;
}
public Date getUpdateTime() {
return updateTime;
}
public void setUpdateTime(Date updateTime) {
this.updateTime = updateTime;
}
@Override
public String toString() {
return "MybatisDO{" +
"id=" + id +
", name='" + name + '\'' +
", version='" + version + '\'' +
", createBy='" + createBy + '\'' +
", updateBy='" + updateBy + '\'' +
", createTime=" + createTime +
", updateTime=" + updateTime +
'}';
}
}
2、创建mapper接口
@Mapper
public interface MybatisMapper {
@Insert("insert into mybatis_do (version,name,create_by,create_time,update_by,update_time) values(#{version},#{name},#{createBy},#{createTime},#{updateBy},#{updateTime})")
int insert(MybatisDO mybatisDO);
@Select("select * from mybatis_do where id = #{id}")
MybatisDO selectOne(@Param("id") Long id);
@Delete("delete from mybatis_do where id = #{id} ")
int delete (Long id);
@Select("select * from mybatis_do")
List<MybatisDO> select();
@Update("update mybatis_do set name = #{name}, version=#{version}, update_by=#{updateBy},update_time=#{updateTime} where id=#{id}")
int update(MybatisDO mybatisDO);
}
3、创建controller类
@RestController
@RequestMapping("mybatis")
public class MybatisController {
@Autowired
private MybatisMapper mapper;
@RequestMapping("insert")
public int insert(@RequestBody MybatisDO mybatisDO){
return mapper.insert(mybatisDO);
}
@RequestMapping("selectone")
public MybatisDO selectone(Long id){
return mapper.selectOne(id);
}
@RequestMapping("delete")
public int delete(Long id){
return mapper.delete(id);
}
@RequestMapping("select")
public List<MybatisDO> select(){
return mapper.select();
}
@RequestMapping("update")
public int update(@RequestBody MybatisDO mybatisDO){
return mapper.update(mybatisDO);
}
}
4.实现接口(这是plugins 拦截器部分)
@Component
@Intercepts({@Signature(method = "update", type = Executor.class, args = {MappedStatement.class, Object.class})})
public class MyBatisInterceptorImpl implements Interceptor {
@Override
public Object intercept(Invocation invocation) throws Throwable {
Object[] args = invocation.getArgs();
MappedStatement statement = (MappedStatement) args[0];
SqlCommandType sqlCommandType = statement.getSqlCommandType();
Date date = new Date();
Object parameter = invocation.getArgs()[1];
Class<?> clazz = parameter.getClass();
Field[] fields = clazz.getDeclaredFields();
if (SqlCommandType.INSERT.equals(sqlCommandType)){
for (Field field : fields) {
field.setAccessible(true);
switch (field.getName()){
case "createBy":
field.set(parameter,"张三");
break;
case "createTime":
field.set(parameter,date);
break;
case "updateBy":
field.set(parameter,"张三");
break;
case "updateTime":
field.set(parameter,date);
break;
}
}
}
if (SqlCommandType.UPDATE.equals(sqlCommandType)){
for (Field field : fields) {
field.setAccessible(true);
switch (field.getName()){
case "updateBy":
field.set(parameter,"李四");
break;
case "updateTime":
field.set(parameter,date);
break;
}
}
}
String sql = statement.getBoundSql(args[1]).getSql();
System.out.println("--------intercept method: " + statement.getId() + "-----sql: " + sql);
Object returnObject = invocation.proceed();
return returnObject;
}
@Override
public Object plugin(Object target) {
return Plugin.wrap(target,this);
}
@Override
public void setProperties(Properties properties) {
}
}
测试
数据库中已经有了,说明插入操作,拦截器起作用了!
再试试更新操作
这里的李四已经更新进去了,说明更新的操作也拦截了,大功告成。
补充
原理
拦截器部分的原理是实现 mybatis 中 Interceptor 接口,这个接口有三个方法intercept,plugin,setProperties,主要在intercept中添加插入逻辑,比如我这里拦截所有的修改操作,这里的修改包括增删改,如果是插入操作,那就向数据库表中插入创建人,创建时间,更新人,更新时间。如果是更新操作,那就将数据库中更新人和更新时间给更新掉。
@Intercepts注解
@Intercepts({@Signature(method = “update”, type = Executor.class, args = {MappedStatement.class, Object.class})})
拦截器注解intercepts包括signature,这里有三个参数,以我这个例子来说,method代表方法操作的,type是类型,agrs是参数;想要更加了解这个的就在网上再搜搜吧,type类型有四种,我这里选的是Executor,四种之一。
配置
将拦截器实现类注入容器的两种方式
1、如这篇文章上在实现类上添加@component注解;
2、添加一个配置类,再添加一个bean,如下:
@Configuration
public class BeanConfig {
@Bean
public MyBatisInterceptorImpl myBatisInterceptor(){
return new MyBatisInterceptorImpl();
}
}