目录
一、Mybatis-Plus。
(1)ActiveRecord。
(2)Oracle 主键Sequence。( 没学过oracle,了解即可)
(3)插件。
(3.1) MybatisPlusInterceptor插件主体。
(3.2)mybatis的插件机制。
(3.3)防全表更新与删除插件。
(3.4)性能插件(在 Mybatis-Plus 3.4.0 版本中被官方废弃)。
(3.5)乐观锁插件。
(4)Sql注入器。
(5)自动填充功能。
(6)逻辑删除。
(7)通用枚举。
(8)代码生成器。(了解即可)
(8.1)代码生成器(新)。
(8.2)代码生成器(旧)。
(9)MybatisX 快速开发插件。
简介:ActiveRecord 是一种常见的设计模式之一。ActiveRecord 是一种面向对象的数据库操作模式,它将数据库表映射为类,将表中的行映射为对象。在 ActiveRecord 模式中,每个类都对应了数据库中的一张表,而每个实例则代表了该表中的一行数据。通过这种方式,可以直接在实例上调用增删改查方法,来完成与数据库的交互。
注意:虽然在使用 Model 类中的方法时不需要显式地调用 UserMapper 接口或其他 Mapper 接口的方法,但是这些接口仍然是 Model 类方法底层实现所必需的,不能删除。
@Test
public void testSelectById() {
User user = new User();
user.setId(2L);
User user1 = user.selectById();
System.out.println(user1);
}
@Test
public void testInsert() {
User user = new User();
user.setUserName("liubei");
user.setPassword("123456");
user.setAge(30);
user.setName("刘备");
user.setMail("[email protected]");
//调用AR的insert方法进行插入数据
boolean insert = user.insert();
System.out.println("result => "+insert);
}
@Test
public void testUpdateById() {
User user = new User();
user.setId(13L);//查询条件
user.setAge(31);//更新数据
boolean result = user.updateById();
System.out.println("result => "+result);
}
@Test
public void testDelete() {
User user = new User();
user.setId(13L);
boolean delete = user.deleteById();
System.out.println("result => "+delete);
}
@Test
public void testSelect() {
User user = new User();
QueryWrapper wrapper = new QueryWrapper<>();
wrapper.ge("age",30);//大于等于30岁的用户查询出来
List userList = user.selectList(wrapper);
for (User user1 : userList) {
System.out.println(user1);
}
}
注意:下面几个小插件要加到这个插件(主体)才能使用。
如果默认支持的拦截器无法满足特定的需求时,也可以在 Executor、ParameterHandler、ResultSetHandler 和 StatementHandler 接口的实现类中编写自定义的方法,并通过拦截器进行拦截和增强。但是这样做需要开发者具备较高的 MyBatis 以及 Java 技术水平以及对 SQL 执行细节的理解。
package mp.plugins;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.plugin.*;
import java.util.Properties;
@Intercepts({@Signature(
type= Executor.class,
method = "update",
args = {MappedStatement.class,Object.class})})
public class MyInterceptor implements Interceptor {
@Override//执行1次
public Object intercept(Invocation invocation) throws Throwable {
//拦截方法,具体业务逻辑编写的位置
return invocation.proceed();
}
@Override//执行了四次,分别拦截了:Executor、ParameterHandler、ResultSetHandler、StatementHandler这四个对象
public Object plugin(Object target) {
//创建target对象的代理对象,目的是将当前拦截器加入到该对象中
return Plugin.wrap(target, this);
}
@Override
public void setProperties(Properties properties) {
//属性设置
}
}
注意:该插件仅适用于开发环境,不 适用于生产环境。
注意!
插件执行链
最后面。如在租户插件前面,会出现 COUNT
执行 SQL
不准确问题。@Configuration
@MapperScan("mp.mapper") //设置mapper接口的扫描包
public class MybatisPlusConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
//这里是添加分页查询的拦截器
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
//这里是添加阻止恶意的全表更新删除的拦截器
interceptor.addInnerInterceptor(new BlockAttackInnerInterceptor());
return interceptor;
}
//注入自定义的拦截器(插件)
@Bean
public MyInterceptor myInterceptor(){
return new MyInterceptor();
}
}
注意:该插件只用于开发环境,不建议生产环境使用。
1、PerformanceInterceptor
类在 Mybatis-Plus 3.4.0 版本中被官方废弃。原因是该拦截器会在每次 SQL 执行时都输出一些日志信息,对性能会有一定的消耗。
2、官方建议使用 p6spy
或者其他 SQL 监控工具来监控 SQL 执行效率,以替代 PerformanceInterceptor
。
3、如果您仍然希望在项目中使用 PerformanceInterceptor
,可以将其版本锁定在 Mybatis-Plus 3.3.2 及以下版本。
mybatis的核心xml方式:
1、这里的 @page
表示要访MybatisPlusInterceptor
类中名为 page
的属性,并将其设置为 com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor
实例。
2、如果使用了 @
符号,就表示某个属性值是一个 SpEL 表达式,需要通过 SpEL 的语法来获取类的实例或者访问类实例中的方法或属性。
3、如果不使用 @
符号,则表示某个属性值是一个字符串常量,不是 SpEL 表达式,需要直接使用该字符串作为属性值。
springboot方式:
@Configuration
@MapperScan("mp.mapper") //设置mapper接口的扫描包
public class MybatisPlusConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
//这里是添加分页查询的拦截器
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
//这里是添加阻止恶意的全表更新删除的拦截器
interceptor.addInnerInterceptor(new BlockAttackInnerInterceptor());
//配置乐观锁
interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
return interceptor;
}
//注入自定义的拦截器(插件)
@Bean
public MyInterceptor myInterceptor(){
return new MyInterceptor();
}
}
FindAll方法:
package mp.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import java.util.List;
public interface MyBaseMapper extends BaseMapper {
List findAll();
//扩展其他的方法
}
FindAll类:
package mp.injectors;
import com.baomidou.mybatisplus.core.injector.AbstractMethod;
import com.baomidou.mybatisplus.core.metadata.TableInfo;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlSource;
public class FindAll extends AbstractMethod {
@Override
public MappedStatement injectMappedStatement(Class> mapperClass, Class> modelClass, TableInfo tableInfo) {
String sql = "select * from " + tableInfo.getTableName();
SqlSource sqlSource = languageDriver.createSqlSource(configuration,sql,modelClass);
return this.addSelectMappedStatementForTable(mapperClass, "findAll", sqlSource, tableInfo);
}
}
注入器:
package mp.injectors;
import com.baomidou.mybatisplus.core.injector.AbstractMethod;
import com.baomidou.mybatisplus.core.injector.AbstractSqlInjector;
import com.baomidou.mybatisplus.core.injector.DefaultSqlInjector;
import java.util.ArrayList;
import java.util.List;
public class MySqlInjector extends DefaultSqlInjector {
@Override
public List getMethodList(Class> mapperClass) {
//获取父类中的集合
List list = new ArrayList<>();
list.addAll(super.getMethodList(mapperClass));
list.add(new FindAll());
return list;
}
}
package mp.handler;
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
@Override //插入数据时填充
public void insertFill(MetaObject metaObject) {
//先获取到password的值,再进行判断,如果为空,就进行填充,如果不为空,就不做处理
Object password = getFieldValByName("password", metaObject);
if (null == password){
setFieldValByName("password","888888",metaObject);
}
}
@Override //更新数据时填充
public void updateFill(MetaObject metaObject) {
}
}
package mp.enums;
import com.baomidou.mybatisplus.annotation.IEnum;
public enum SexEnum implements IEnum {
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;
}
}
package mp;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
import com.baomidou.mybatisplus.core.exceptions.MybatisPlusException;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.InjectionConfig;
import com.baomidou.mybatisplus.generator.config.DataSourceConfig;
import com.baomidou.mybatisplus.generator.config.FileOutConfig;
import com.baomidou.mybatisplus.generator.config.GlobalConfig;
import com.baomidou.mybatisplus.generator.config.PackageConfig;
import com.baomidou.mybatisplus.generator.config.StrategyConfig;
import com.baomidou.mybatisplus.generator.config.TemplateConfig;
import com.baomidou.mybatisplus.generator.config.po.TableInfo;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;
/**
*
* mysql 代码生成器演示例子
*
*/
public class MysqlGenerator {
/**
*
* 读取控制台内容
*
*/
public static String scanner(String tip) {
Scanner scanner = new Scanner(System.in);
StringBuilder help = new StringBuilder();
help.append("请输入" + tip + ":");
System.out.println(help.toString());
if (scanner.hasNext()) {
String ipt = scanner.next();
if (StringUtils.isNotEmpty(ipt)) {
return ipt;
}
}
throw new MybatisPlusException("请输入正确的" + tip + "!");
}
/**
* RUN THIS
*/
public static void main(String[] args) {
// 代码生成器
AutoGenerator mpg = new AutoGenerator();
// 全局配置
GlobalConfig gc = new GlobalConfig();
String projectPath = System.getProperty("user.dir");
gc.setOutputDir(projectPath + "/src/main/java");
gc.setAuthor("itcast");
gc.setOpen(false);
mpg.setGlobalConfig(gc);
// 数据源配置
DataSourceConfig dsc = new DataSourceConfig();
dsc.setUrl("jdbc:mysql://127.0.0.1:3306/mp? useUnicode=true&useSSL=false&characterEncoding=utf8");
// dsc.setSchemaName("public");
dsc.setDriverName("com.mysql.cj.jdbc.Driver");
dsc.setUsername("root");
dsc.setPassword("tan");
mpg.setDataSource(dsc);
// 包配置
PackageConfig pc = new PackageConfig();
pc.setModuleName(scanner("模块名"));
pc.setParent("cn.itheima");
mpg.setPackageInfo(pc);
// 自定义配置
InjectionConfig cfg = new InjectionConfig() {
@Override
public void initMap() {
// to do nothing
}
};
List focList = new ArrayList<>();
focList.add(new FileOutConfig("/templates/mapper.xml.ftl") {
@Override
public String outputFile(TableInfo tableInfo) {
// 自定义输入文件名称
return projectPath + "/src/main/resources/mapper/" + pc.getModuleName() + "/" + tableInfo.getEntityName() + "Mapper" + StringPool.DOT_XML;
}
});
cfg.setFileOutConfigList(focList);
mpg.setCfg(cfg);
mpg.setTemplate(new TemplateConfig().setXml(null));
// 策略配置
StrategyConfig strategy = new StrategyConfig();
strategy.setNaming(NamingStrategy.underline_to_camel);
strategy.setColumnNaming(NamingStrategy.underline_to_camel);
//strategy.setSuperEntityClass("com.baomidou.mybatisplus.samples.generator.common.BaseE ntity");
strategy.setEntityLombokModel(true);
//strategy.setSuperControllerClass("com.baomidou.mybatisplus.samples.generator.common.B aseController");
strategy.setInclude(scanner("表名"));
strategy.setSuperEntityColumns("id");
strategy.setControllerMappingHyphenStyle(true);
strategy.setTablePrefix(pc.getModuleName() + "_");
mpg.setStrategy(strategy);
// 选择 freemarker 引擎需要指定如下加,注意 pom 依赖必须有!
mpg.setTemplateEngine(new FreemarkerTemplateEngine());
mpg.execute();
}
}