Mybatis Plus深入
ActiveRecord
· ActiveRecord也属于ORM(对象关系映射)层,由Rails最早提出,遵循标准的ORM模型:表映射到记录,记录映射到对象,字段映射到对象属性。配合遵循的命名和配置惯例,能够很大程度的快速实现模型的操作,而且简洁易懂。
· ActiveRecord的主要思想是:
? 1. 每一个数据库表对应创建一个类,类的每一个对象实例对应于数据库中表的一行记录;通常表的每个字段在类中都有相应的Field;
? 2. ActiveRecord同时负责把自己持久化,在ActiveRecord中封装了对数据库的访问,即CURD;;
3. ActiveRecord是一种领域模型(Domain Model),封装了部分业务逻辑;
如何使用AR
· 在MP中,开启AR非常简单,只需要将实体对象继承Model即可
public class User extends Model<User>
根据主键查询
public void testAR() {
User user = new User(); user.setId(2L);
User user2 = user.selectById();
System.out.println(user2);
}
更新数据
public void testAR() {
User user = new User();
user.setName("刘备");
user.setAge(30);
user.setPassword("123456");
user.setUserName("liubei"); user.setEmail("liubei@itcast.cn");
boolean insert = user.insert();
System.out.println(insert);
}
更新操作
public void testAR() {
User user = new User();
user.setId(8L);
user.setAge(35);
boolean update = user.updateById();
System.out.println(update); }
删除操作
public void testAR() {
User user = new User();
user.setId(7L);
boolean delete = user.deleteById();
System.out.println(delete); }
根据条件查询
public void testAR() {
User user = new User(); QueryWrapper<User>
userQueryWrapper = new QueryWrapper<>();
userQueryWrapper.le("age","20");
List<User> users = user.selectList(userQueryWrapper);
for (User user1 : users) {
System.out.println(user1);
}
Oracle 主键Sequence
· 在mysql中,主键往往是自增长的,这样使用起来是比较方便的,如果使用的是Oracle数据库,那么就不能使用自增长了,就得使用Sequence 序列生成id值了
部署Oracle环境
· 为了简化环境部署,这里使用Docker环境进行部署安装Oracle
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jYxi4ddN-1646627908009)(C:\Users\maybe3032\AppData\Roaming\Typora\typora-user-images\image-20220306214745790.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9QQCTJ4O-1646627908010)(C:\Users\maybe3032\AppData\Roaming\Typora\typora-user-images\image-20220306214755428.png)]
· 使用navicat12进行连接并操作oracle
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TEsqxxkN-1646627908011)(C:\Users\maybe3032\AppData\Roaming\Typora\typora-user-images\image-20220306214831712.png)]
创建表以及序列
CREATE TABLE "TB_USER" (
"ID" NUMBER(20) VISIBLE NOT NULL ,
"USER_NAME" VARCHAR2(255 BYTE) VISIBLE ,
"PASSWORD" VARCHAR2(255 BYTE) VISIBLE ,
"NAME" VARCHAR2(255 BYTE) VISIBLE ,
"AGE" NUMBER(10) VISIBLE ,
"EMAIL" VARCHAR2(255 BYTE) VISIBLE
)
CREATE SEQUENCE SEQ_USER START WITH 1 INCREMENT BY 1
jdbc驱动包
· 将驱动包安装到本地仓库
mvn install:install-file -DgroupId=com.oracle -DartifactId=ojdbc8 -Dversion=12.1.0.1 - Dpackaging=jar -Dfile=ojdbc8.jar
· 安装完成后的坐标
<dependency>
<groupId>com.oracle</groupId>
<artifactId>ojdbc8</artifactId>
<version>12.1.0.1</version>
</dependency>
application.properties
#数据库连接配置
spring.datasource.driver-class-name=oracle.jdbc.OracleDriver spring.datasource.url=jdbc:oracle:thin:@192.168.31.81:1521:xe spring.datasource.username=system spring.datasource.password=oracle
#id生成策略
mybatis-plus.global-config.db-config.id-type=input
配置序列
第一:配置MP的序列生成器到Spring容器
@Bean
public OracleKeyGenerator oracleKeyGenerator(){
return new OracleKeyGenerator();
}
第二:在实体对象中指定序列的名称
@KeySequence(value = "SEQ_USER", clazz = Long.class)
public class User{
......
}
插件
Mybatis的插件机制
· MyBatis 允许你在已映射语句执行过程中的某一点进行拦截调用
· 默认情况下,MyBatis 允许使用插件来拦截的方法
调用包括:
-
Executor (update, query, flflushStatements, commit, rollback, getTransaction, close, isClosed) -
ParameterHandler (getParameterObject, setParameters) -
ResultSetHandler (handleResultSets, handleOutputParameters) -
StatementHandler (prepare, parameterize, batch, update, query)
· 可以拦截Executor接口的部分方法,比如update,query,commit,rollback等方法
· 总体概括为:
-
拦截执行器的方法 -
拦截参数的处理 -
拦截结果集的处理 -
拦截Sql语法构建的处理
@Intercepts({@Signature(
type= Executor.class,
method = "update",
args = {MappedStatement.class,Object.class})})
public class MyInterceptor implements Interceptor {
@Override
public Object intercept(Invocation invocation) throws Throwable {
return invocation.proceed();
}
@Override
public Object plugin(Object target) {
return Plugin.wrap(target, this);
}
@Override public void setProperties(Properties properties) {
}
}
注入到Spring容器
@Bean
public MyInterceptor myInterceptor(){
return new MyInterceptor();
}
或者通过xml配置,mybatis-confifig.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<plugins>
<plugin interceptor="cn.itcast.mp.plugins.MyInterceptor">
</plugin>
</plugins>
</configuration>
执行分析插件
· 在MP中提供了对SQL执行的分析的插件,可用作阻断全表更新、删除的操作,注意:该插件仅适用于开发环境,不适用于生产环境
@Bean
public SqlExplainInterceptor sqlExplainInterceptor(){ SqlExplainInterceptor sqlExplainInterceptor = new SqlExplainInterceptor();
List<ISqlParser> sqlParserList = new ArrayList<>();
sqlParserList.add(new BlockAttackSqlParser()); sqlExplainInterceptor.setSqlParserList(sqlParserList);
return sqlExplainInterceptor;
}
结果:执行全表更新时,会抛出异常,这样有效防止了一些误操作
性能分析插件
· 性能分析拦截器,用于输出每条 SQL 语句及其执行时间,可以设置最大执行时间,超过时间会抛出异常
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<plugins>
<plugin interceptor="com.baomidou.mybatisplus.extension.plugins.PerformanceInterceptor">
<property name="maxTime" value="100" />
<property name="format" value="true" />
</plugin>
</plugins>
</configuration>
乐观锁插件
适用场景
· 当要更新一条记录的时候,希望这条记录没有被别人更新
乐观锁实现方式:
- 取出记录时,获取当前version
- 更新时,带上这个version
- 执行更新时, set version = newVersion where version = oldVersion
- 如果version不对,就更新失败
插件配置
spring xml:
<bean class="com.baomidou.mybatisplus.extension.plugins.OptimisticLockerInterceptor"/>
spring boot:
@Bean
public OptimisticLockerInterceptor optimisticLockerInterceptor() {
return new OptimisticLockerInterceptor();
}
注解实体字段
· 需要为实体字段添加@Version注解
//表添加version字段,并且设置初始值为1
ALTER TABLE `tb_user`
ADD COLUMN `version` int(10) NULL AFTER `email`;
UPDATE `tb_user` SET `version`='1';
@Version
private Integer version;
· 更新的条件中有version条件,并且更新的version为2
· 如果再次执行,更新则不成功。这样就避免了多人同时更新时导致数据的不一致
特别说明
- 支持的数据类型有:int,Integer,long,Long,Date,Timestamp,LocalDateTime
- 整数类型下 newVersion = oldVersion + 1
- newVersion 会回写到 entity 中
- 仅支持 updateById(id) 与 update(entity, wrapper) 方法
- 在 update(entity, wrapper) 方法下, wrapper不能复用
Sql 注入器
· 在MP中,通过AbstractSqlInjector将BaseMapper中的方法注入到了Mybatis容器, 这些方法才可以正常执行。
· 如何扩充BaseMapper中的方法
编写MyBaseMapper
public interface MyBaseMapper<T> extends BaseMapper<T> {
List<T> findAll();
}
· Mapper都可以继承该Mapper,这样实现了统一的扩展
public interface UserMapper extends MyBaseMapper<User> {
User findById(Long id);
}
编写MySqlinjector
public class MySqlInjector extends DefaultSqlInjector {
@Override
public List<AbstractMethod> getMethodList() {
List<AbstractMethod> methodList = super.getMethodList();
methodList.add(new FindAll());
list.add(new FindAll());
return methodList;
}
}
编写FindAll
public class FindAll extends AbstractMethod {
@Override public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
String sqlMethod = "findAll";
String sql = "select * from " + tableInfo.getTableName();
SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass);
return this.addSelectMappedStatement(mapperClass, sqlMethod, sqlSource, modelClass, tableInfo);
}
}
注册到Spring容器
@Bean
public MySqlInjector mySqlInjector(){
return new MySqlInjector();
}
· 实现了全局扩展SQL注入器
自动填充功能
· 有些时候我们可能会有这样的需求,插入或者更新数据时,希望有些字段可以自动填充数据,比如密码、version等。在MP中提供了这样的功能,可以实现自动填充
添加@TablleField注解
@TableField(fill = FieldFill.INSERT)
private String password;
· 为password添加自动填充功能,在新增数据时有效
· FieldFill提供了多种模式选择
public enum FieldFill {
DEFAULT,
INSERT,
UPDATE,
INSERT_UPDATE
}
编写MyMetaObjectHandler
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
@Override
public void insertFill(MetaObject metaObject) {
Object password = getFieldValByName("password", metaObject);
if(null == password){
setFieldValByName("password", "123456", metaObject);
}
}
@Override
public void updateFill(MetaObject metaObject) {
}
}
逻辑删除
· 开发系统时,有时候在实现功能时,删除操作需要实现逻辑删除,所谓逻辑删除就是将数据标记为删除,而并非真正的物理删除(非DELETE操作),查询时需要携带状态条件,确保被标记的数据不被查询到。这样做的目的就是避免数据被真正的删除。
修改表结构
· 为tb_user表增加deleted字段,用于表示数据是否被删除,1代表删除,0代表未删除
ALTER TABLE `tb_user`
ADD COLUMN `deleted` int(1) NULL DEFAULT 0 COMMENT '1代表删除,0代表未删除' AFTER `version`;
· 修改User实体,增加deleted属性并且添加@TableLogic注解
@TableLogic
private Integer deleted;
配置
application.properties:
# 逻辑已删除值(默认为 1)
mybatis-plus.global-config.db-config.logic-delete-value=1
# 逻辑未删除值(默认为 0)
mybatis-plus.global-config.db-config.logic-not-delete-value=0
通用枚举
· 解决了繁琐的配置,让 mybatis 优雅的使用枚举属性
修改表结构
ALTER TABLE `tb_user`
ADD COLUMN `sex` int(1) NULL DEFAULT 1 COMMENT '1-男,2-女' AFTER `deleted`;
定义枚举
public enum SexEnum implements IEnum<Integer> {
MAN(1,"男"),
WOMAN(2,"女");
private int value;
private String desc;
SexEnum(int value, String desc) {
this.value = value;
this.desc = desc;
}
@Override
public Integer getValue() {
return this.value;
}
@Override
public String toString() {
return this.desc;
}
}
配置
# 枚举包扫描
mybatis-plus.type-enums-package=cn.itcast.mp.enums
修改实体
private SexEnum sex;
代码生成器
· AutoGenerator 是 MyBatis-Plus 的代码生成器,通过 AutoGenerator 可以快速生成 Entity、Mapper、Mapper、XML、Service、Controller 等各个模块的代码,极大的提升了开发效率
创建工程
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.4.RELEASE</version>
</parent>
<groupId>cn.itcast.mp</groupId>
<artifactId>itcast-mp-generator</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.1.1</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>3.1.1</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
代码
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XK8XTrZ6-1646627908012)(C:\Users\maybe3032\AppData\Roaming\Typora\typora-user-images\image-20220307123449083.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pnxh0Hnx-1646627908013)(C:\Users\maybe3032\AppData\Roaming\Typora\typora-user-images\image-20220307123503817.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bqGQ4LRj-1646627908014)(C:\Users\maybe3032\AppData\Roaming\Typora\typora-user-images\image-20220307123513837.png)]
MybatisX 快速开发插件
· MybatisX 是一款基于 IDEA 的快速开发插件,为效率而生。
· 安装方法:打开 IDEA,进入 File -> Settings -> Plugins -> Browse Repositories,输入 mybatisx 搜索并安装
功能:
· Java 与 XML 调回跳转
· Mapper 方法自动生成 XML
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2CSpOWl3-1646627908014)(C:\Users\maybe3032\AppData\Roaming\Typora\typora-user-images\image-20220307123634106.png)]
|