Mybatis-Puls (下文简称MP)
如何在SpringBoot中使用
1、首先,引入相关的依赖
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.1</version>
</dependency>
2、在application.yml文件配置MP的相关属性
mybatis-plus:
configuration:
# 在映射实体或者属性时,将数据库中表名和字段名中的下划线去掉,按照驼峰命名法映射
# 举两个栗子 表名:address_book -->实体类名: AddressBook 字段名:user_name --> 属性名:userName
map-underscore-to-camel-case: true
# 开启控制台SQL日志打印
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
global-config:
db-config:
# 指定主键生成策略 assign_id 采用雪花算法
id-type: assign_id
如何使用MP的CRUD
mapper层
-
继承MP提供的
BaseMapper<T>
类,并指定泛型@Mapper public interface EmployeeMapper extends BaseMapper<Employee> { }
service接口层
-
继承MP提供的
IService<T>
接口,并指定泛型public interface EmployeeService extends IService<Employee> { }
service实现类层
-
继承MP提供的
ServiceImpl<M, T>
,指定泛型,实现 service 接口@Service public class EmployeeServiceImpl extends ServiceImpl<EmployeeMapper, Employee> implements EmployeeService { }
需要指定两个泛型,第一个是Mapper,第二个是实体类
如何使用MP的分页插件
- 先搞一个配置类
/**
* @author JUNHAO
* 配置Mybatis-Plus分页插件
*/
@Configuration
public class MybatisPlusConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
return interceptor;
}
}
MP 公共字段自动填充如何实现
在很多场景下,我们需要对某些字段经常的进行填充,比如,员工信息的更新时间、修改时间,也就是在插入或者更新的时候为指定字段赋予指定的值,使用它的好处就是可以统一对这些字段进行处理,避免了重复代码
实现步骤:
-
为需要自动填充的公共字段添加
@TableField
注解,指定自动填充的策略/** * 员工创建时间 */ @TableField(fill = FieldFill.INSERT) // 插入时填充字段 private LocalDateTime createTime; /** * 员工信息更新时间 */ @TableField(fill = FieldFill.INSERT_UPDATE) // 插入和更新时填充字段 private LocalDateTime updateTime; /** * 创建人 */ @TableField(fill = FieldFill.INSERT) //插入时填充字段 private Long createUser; /** * 更新人 */ @TableField(fill = FieldFill.INSERT_UPDATE) // 插入和更新时填充字段 private Long updateUser;
-
创建一个类,类名叫什么不重要,关键是要实现
MetaObjectHandler
接口,并实现它的两个方法/** * @author JUNHAO * 自定义元数据对象处理器 */ @Component @Slf4j public class MyMetaObjectHandler implements MetaObjectHandler { /** * 插入操作自动填充 * @param metaObject */ @Override public void insertFill(MetaObject metaObject) { metaObject.setValue("createTime", LocalDateTime.now()); metaObject.setValue("updateTime", LocalDateTime.now()); metaObject.setValue("createUser", new Long(1)); metaObject.setValue("updateUser", new Long(1)); } /** * 更新操作自动填充 * @param metaObject */ @Override public void updateFill(MetaObject metaObject) { metaObject.setValue("updateTime", LocalDateTime.now()); metaObject.setValue("updateUser", new Long(1)); } }
出现了一个问题,我们需要填充更新人的id和创建人的id,但是我们又无法通过request去拿session中的数据,这个时候怎么办呢,且看下文。
接上文,我们可以借助ThreadLocal来获取当前登陆用户的id
什么是ThreadLocal
ThreadLocal并不是一个Thread,而是Thread的局部变量。当使用ThreadLocal维护变量时,ThreadLocal为每个使用该变量的线程提供独立的变量副本,所以每一个线程都可以独立地改变自己的副本,而不会影响其他线程所对应地副本。
ThreadLocal为每个线程提供单独一份存储空间,具有线程隔离地效果,只有在线程内才能获取到对应的值,线程外则不能访问。
ThreadLocal常用方法:
- public void set(T value) 设置当前线程地线程局部变量的值
- public T get() 返回当前线程所对应的线程局部变量的值
1、创建一个类
BaseContext
/** * @author JUNHAO * 基于ThreadLocal封装工具类,用户保存和获取当前登陆的id */ public class BaseContext { private static ThreadLocal<Long> threadLocal = new ThreadLocal<>(); /** * 设置值 * @param id */ public static void setCurrentId(Long id) { threadLocal.set(id); } /** * 获取值 * @return */ public static Long getCurrentId() { return threadLocal.get(); } }
2、在可以获取到用户id的方法中调用我们封装的工具类将用户id放入ThreadLocal
// ... Long empId = (Long) request.getSession().getAttribute("employee"); BaseContext.setCurrentId(empId); // ...
3、在需要获取用户id的地方调用获取id的方法
/** * @author JUNHAO * 自定义元数据对象处理器 */ @Component @Slf4j public class MyMetaObjectHandler implements MetaObjectHandler { /** * 插入操作自动填充 * @param metaObject */ @Override public void insertFill(MetaObject metaObject) { metaObject.setValue("createTime", LocalDateTime.now()); metaObject.setValue("updateTime", LocalDateTime.now()); metaObject.setValue("createUser", BaseContext.getCurrentId()); metaObject.setValue("updateUser", BaseContext.getCurrentId()); } /** * 更新操作自动填充 * @param metaObject */ @Override public void updateFill(MetaObject metaObject) { log.info("当前线程id{}", Thread.currentThread().getId()); metaObject.setValue("updateTime", LocalDateTime.now()); metaObject.setValue("updateUser", BaseContext.getCurrentId()); } }
问题解决