做网站公司-汉狮网络,营销型网站用什么模版合适,金融网站推广圳seo公司,国家工商登记网在 MyBatis-Plus 3.x 中#xff0c;自动填充的插件方式发生了变化。现在推荐使用 MetaObjectHandler 接口的实现类来定义字段的填充逻辑。以下是使用 MyBatis-Plus 3.x 自动填充的基本步骤#xff1a;
1.基本配置
1.1添加 Maven 依赖#xff1a;
确保你的 Maven 依赖中使…在 MyBatis-Plus 3.x 中自动填充的插件方式发生了变化。现在推荐使用 MetaObjectHandler 接口的实现类来定义字段的填充逻辑。以下是使用 MyBatis-Plus 3.x 自动填充的基本步骤
1.基本配置
1.1添加 Maven 依赖
确保你的 Maven 依赖中使用的是 MyBatis-Plus 3.x 版本。
dependencies!-- MyBatis-Plus 核心依赖 --dependencygroupIdcom.baomidou/groupIdartifactIdmybatis-plus-boot-starter/artifactIdversion最新版本/version/dependency!-- 其他依赖... --
/dependencies1.2 配置 MyBatis-Plus 自动填充
1.2.1使用Component注解
创建一个实现 MetaObjectHandler 接口的配置类用于定义字段填充逻辑。
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;import java.time.LocalDateTime;Component
public class MyMetaObjectHandler implements MetaObjectHandler {Overridepublic void insertFill(MetaObject metaObject) {this.strictInsertFill(metaObject, createTime, LocalDateTime.class, LocalDateTime.now());this.strictInsertFill(metaObject, updateTime, LocalDateTime.class, LocalDateTime.now());}Overridepublic void updateFill(MetaObject metaObject) {this.strictUpdateFill(metaObject, updateTime, LocalDateTime.class, LocalDateTime.now());}
}这种方式是 MyBatis-Plus 3.x 中推荐的字段自动填充方式。在这个示例中MyMetaObjectHandler 类上添加了 Component 注解确保 Spring Boot 能够自动扫描到并注册为 Bean。这样MyBatis-Plus 在执行插入和更新操作时会自动调用 MetaObjectHandler 中的对应方法进行字段填充
1.2.1 使用BeanConfiguration注解
当然也可以使用bean的方式在mybatisConfig里面注入 import com.sky.handler.MyMetaObjectHandler;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;Configuration
public class MyBatisPlusConfig {Beanpublic MyMetaObjectHandler myMetaObjectHandler() {return new MyMetaObjectHandler();}
}import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;import java.time.LocalDateTime;Slf4j
public class MyMetaObjectHandler implements MetaObjectHandler {Overridepublic void insertFill(MetaObject metaObject) {log.info(开始插入时自动填充);this.strictInsertFill(metaObject, createTime, LocalDateTime.class, LocalDateTime.now());this.strictInsertFill(metaObject, updateTime, LocalDateTime.class, LocalDateTime.now());}Overridepublic void updateFill(MetaObject metaObject) {log.info(开始更新时自动填充);this.strictUpdateFill(metaObject, updateTime, LocalDateTime.class, LocalDateTime.now());}
}但是用这种方式的时候需要注意MyMetaObjectHandler这个类前面不能加Component否则会造成bean冲突。
定义实体类 在实体类中定义需要自动填充的字段
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;import java.time.LocalDateTime;Data
TableName(your_table_name)
public class YourEntity {TableIdprivate Long id;private String name;// 其他字段省略...// createTime 和 updateTime 字段将由 MyBatis-Plus 自动填充TableField(fill FieldFill.INSERT)private LocalDateTime createTime;TableField(fill FieldFill.INSERT_UPDATE)private LocalDateTime updateTime;
}确保你的实体类中的字段类型和配置的 MetaObjectHandler 中的类型一致。
。
这样达到的实际效果就是
我们在封装好入库的对象的时候没有setUpdateTime这个属性那么执行intsert 和 update操作的之后数据库中也会向UpdateTime存入值。
下面我们需要对一些细节说明一下
2. 严格模式与非严格模式
this.strictInsertFill(metaObject, createTime, LocalDateTime.class, LocalDateTime.now());在这个示例中MyMetaObjectHandler 实现了 MetaObjectHandler 接口并在 insertFill 和 updateFill 方法中定义了字段填充的逻辑。strictInsertFill 和 strictUpdateFill 方法用于严格模式的字段填充。
非严格模式 在非严格模式下字段填充通常会在任何情况下都执行即使字段的值已经被手动设置或者数据库中已经有了一个值。这样可能导致字段值被多次更新。
严格模式 相比之下严格模式会更加谨慎。在严格模式下字段填充只会在满足一定条件的情况下才执行。例如在插入操作时只有在字段的值为 null 时才会进行填充。在更新操作时只有在字段的值为 null 或者被标记为需要更新时才会进行填充。
3.自动插入的时机
上述的自动填充操作是发生在数据库层面的
具体说是在 MyBatis 执行 SQL 语句时MyBatis-Plus 框架会拦截这些 SQL 操作根据配置的自动填充规则来动态生成相应的字段值然后执行相应的 SQL 操作。这样可以在数据库层面确保这些字段的值符合预期。
插入操作 当执行插入 SQL 语句时MyBatis-Plus 拦截器会在插入前执行 MetaObjectHandler 的 insertFill 方法填充相应字段的值然后将填充后的 SQL 语句发送给数据库执行。
更新操作 同理对于更新 SQL 语句MyBatis-Plus 会在更新前执行 MetaObjectHandler 的 updateFill 方法填充相应字段的值然后将填充后的 SQL 语句发送给数据库执行。
这样做的好处是在数据库层面确保了字段填充的一致性避免了手动在 Service 层面或者 Controller 层面进行填充减少了代码冗余和错误的可能性。这也是 MyBatis-Plus 提供的一种便捷的开发方式使得开发者可以更专注于业务逻辑而不用过多关心数据库层面的操作。
注意上述操作并不是废话我们来看这样一个例子这个例子是我实际项目中的例子我们只需要关注自动填充相关的部分就可以
实体类
Data
Builder
NoArgsConstructor
AllArgsConstructor
TableName(employee)
public class Employee implements Serializable {private static final long serialVersionUID 1L;TableId(type IdType.AUTO)//自增主键private Long id;TableField(insertStrategy FieldStrategy.NOT_EMPTY)private String username;TableField(insertStrategy FieldStrategy.NOT_EMPTY)private String name;TableField(insertStrategy FieldStrategy.NOT_EMPTY)private String password;TableField(insertStrategy FieldStrategy.NOT_EMPTY)private String phone;TableField(insertStrategy FieldStrategy.NOT_EMPTY)EnumValue()private String sex;TableField(value id_number,insertStrategy FieldStrategy.NOT_NULL)private String idNumber;private EmployeeStatus status;JsonFormat(pattern yyyy-MM-dd HH:mm:ss)TableField(fill FieldFill.INSERT)//表示该字段只会在插入的填充private LocalDateTime createTime;JsonFormat(pattern yyyy-MM-dd HH:mm:ss)TableField(fill FieldFill.INSERT_UPDATE)//表示这个字段只会在传入和更改的时候都会填充private LocalDateTime updateTime;TableField(fill FieldFill.INSERT)//表示该字段只会在插入的填充private Long createUser;TableField(fill FieldFill.INSERT_UPDATE)//表示该字段只会在插入的填充private Long updateUser;
}}我的自动填充是这样写的
Slf4j
public class MyMetaObjectHandler implements MetaObjectHandler {Overridepublic void insertFill(MetaObject metaObject) {log.info(开始插入时自动填充);this.strictInsertFill(metaObject, createTime, LocalDateTime.class, LocalDateTime.now());this.strictInsertFill(metaObject, updateTime, LocalDateTime.class,LocalDateTime.now());}Overridepublic void updateFill(MetaObject metaObject) {log.info(开始更新时自动填充);this.strictUpdateFill(metaObject, updateTime,LocalDateTime.class, LocalDateTime.of(2022,12,30,5,6,0));}
}我这里写了一个测试类
SpringBootTest
class SkyApplicationTest {ResourceEmployeeMapper employeeMapper;Testpublic void test() {LambdaUpdateWrapperEmployee lambdaUpdateWrapper new LambdaUpdateWrapper();lambdaUpdateWrapper.eq(Employee::getName,张三);lambdaUpdateWrapper.set(Employee::getPhone,2222222222);Employee employee new Employee();employee.setPhone(111111111);employeeMapper.update(employee,lambdaUpdateWrapper);System.out.println();}}那么这个sql执行的结果是什么
UPDATEemployee SETphone111111111,update_time2022-12-30T05:06,update_usernull,phone2222222222 WHERE(name 张三);这个sql为什么是这样的
我们先看phone这个字段 phone这个字段是没有设置自动填充的但是两个入参实体类Employee和更新条件LambdaUpdateWrapper都对phone都对phone设置了值。 通过sql我们不难发现mybatis-plus会先根据实体类中不为null的值进行set,然后再写入更新条件中的set 所以最后更新到数据库里谁写在SQL语句的最后数据库里的值就会是谁。
下面 update_time2022-12-30T05:06,update_usernull,这两个字段都是自动填充设置的其中update_time‘2022-12-30T05:06’,是我设置了固定值而update_usernull是因为我没在MyMetaObjectHandler里设置值的原因才会赋值为null.
那么现在的问题是自动插入的时机在哪呢
我们不妨构建这样的例子 Overridepublic void insertFill(MetaObject metaObject) {log.info(开始插入时自动填充);this.strictInsertFill(metaObject, createTime, LocalDateTime.class, LocalDateTime.now());this.strictInsertFill(metaObject, updateTime, LocalDateTime.class,LocalDateTime.now());this.strictInsertFill(metaObject,updateUser,Long.class,1L);this.strictInsertFill(metaObject,createUser,Long.class,1L);}Overridepublic void updateFill(MetaObject metaObject) {log.info(开始更新时自动填充);this.strictUpdateFill(metaObject, updateTime,LocalDateTime.class, LocalDateTime.of(2022,12,30,5,6,0));this.strictInsertFill(metaObject,updateUser,Long.class,1L);}自动填充的时候uptdateUser会被填入1L
Testpublic void test() {LambdaUpdateWrapperEmployee lambdaUpdateWrapper new LambdaUpdateWrapper();lambdaUpdateWrapper.eq(Employee::getName,张三);lambdaUpdateWrapper.set(Employee::getUpdateUser,2L);Employee employee new Employee();employee.setUpdateUser(3L);employeeMapper.update(employee,lambdaUpdateWrapper);System.out.println();}而在测试类中。实体类Employee中的updateUser值是3L 查询条件中的updateUser是2L
那么形成的SQL是什么样的呢
/*17 2023-12-17 16:52:32 */UPDATEemployee SETupdate_time2022-12-30T05:06,update_user3,update_user2 WHERE(name 张三);先update_user 3,后update_user 2,这个之前就解释过了 但是update 1怎么没有呢
这是因为前面说的我们在设置自动填充时遵循的时严格模式的插入当执行update操作的时候如果该实体类中的updat_user不为null就不会触发字段填充。
严格模式下的填充规则 插入时填充规则INSERT
当执行插入操作时只有在实体类的字段的值为 null 时才进行填充。 如果实体类字段的值不为 null则填充操作会被忽略。 更新时填充规则UPDATE
当执行更新操作时只有在字段的值为 null 或者字段被标记为需要更新时才进行填充。 如果字段的值不为 null且字段没有被标记为需要更新填充操作会被忽略。
一定一定注意是实体类中的字段值为null
我们将测试类更改一下 SpringBootTest
class SkyApplicationTest {ResourceEmployeeMapper employeeMapper;Testpublic void test() {LambdaUpdateWrapperEmployee lambdaUpdateWrapper new LambdaUpdateWrapper();lambdaUpdateWrapper.eq(Employee::getName,张三);lambdaUpdateWrapper.set(Employee::getUpdateUser,2L);Employee employee new Employee();
// employee.setUpdateUser(3L);employeeMapper.update(employee,lambdaUpdateWrapper);System.out.println();}}我们将实体类中updateUser设置为null
你会发现生成的SQL语言是 UPDATEemployee SETupdate_time2022-12-30T05:06,update_user1,update_user2 WHERE(name 张三);会发现自动填充是触发了的。 并且在lambdaUpdateWrapper这个更新条件的前面。这是因为本质上自动填充是给实体类的update_time赋值的。
此外还有一个注意点有一种情况也会导致自动填充失效。
在mybatispluss的官网也有说明。 https://baomidou.com/pages/4c6bcf/
看下面这个例子
SpringBootTest
class SkyApplicationTest {ResourceEmployeeMapper employeeMapper;Testpublic void test() {LambdaUpdateWrapperEmployee lambdaUpdateWrapper new LambdaUpdateWrapper();lambdaUpdateWrapper.eq(Employee::getName,张三);lambdaUpdateWrapper.set(Employee::getUpdateUser,2L);// Employee employee new Employee();
// employee.setUpdateUser(3L);employeeMapper.update(null,lambdaUpdateWrapper);System.out.println();}}他的sql实际为
UPDATEemployee SETupdate_user2 WHERE(name 张三);之所以会这样update的实体类入参是null,自动填充根本就没有启动。
所以当我们的实体类在定义的时候使用了TableField(fill FieldFill.*****)的时候使用mybatis-plus自带的update方法的时候一定不能传null的实体类。可以传new my_entity()过来。