ActiveRecord
ActiveRecord(简称AR)一直广受动态语言(PHP、Ruby等)的喜爱,而java作为准静态语言,对于ActiveRecord往往只能感叹器优雅
什么是ActiveRecord?
ActiveRecord也属于ORM(对象关系映射)层,由Rails最早提出,遵循标准的ORM模型:表映射到记录,记录映射到对象,字段映射到对象属性。配合遵循的命名和配置惯例,能够很大程度的实现模型的操作,而且简洁易懂
ActiveRecord的主要思想是:
- 每一个数据库表对应创建一个类,类的每个对象实例对应于数据库表的一行记录;通常表的每个字段在类中都有相应的Field
- ActiveRecord同时负责把自己持久化,在ActiveRecord中封装了对数据库的访问,即CRUD
- ActiveRecord是一种领域模型(Domain Model),封装了部分业务配置
快速使用
在MP中,开启AR非常简单,只需要将实体对象继承Model即可
注意:先将数据库的tb_user表改为user
将实体对象继承Model
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User extends Model<User> {
private Long id;
private String userName;
private String password;
private String name;
private Integer age;
private String email;
}
根据主键查询
@Test
public void testAR() {
User user = new User();
user.setId(2L);
User user1 = user.selectById();
System.out.println(user1);
}
效果:
新增数据
@Test
public void testAR2() {
User user = new User();
user.setUserName("liubei");
user.setAge(30);
user.setName("刘备");
user.setPassword("123456");
user.setEmail("liubei@dc.cn");
boolean insert = user.insert();
System.out.println(insert);
}
效果:
更新操作
@Test
public void testAR3() {
User user = new User();
user.setId(8L);
user.setAge(35);
boolean b = user.updateById();
System.out.println(b);
}
效果:
删除操作
@Test
public void testAR4() {
User user = new User();
user.setId(7L);
boolean b = user.deleteById();
System.out.println(b);
}
效果:
根据条件查询
@Test
public void testAR5() {
User user = new User();
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.le("age", 24);
List<User> users = user.selectList(wrapper);
for (User user1 : users) {
System.out.println(user1);
}
}
效果:
插件
mybatis的插件机制
MyBatis允许在已映射语句执行过程中的某一点进行拦截调用。默认情况下,MyBatis允许使用插件来拦截的方法调用包括:
- Executor(update, query, flushStatements, commit, rollback, getTransaction, close, isClosed)
- ParameterHandler(getParameterObject, setParameters)
- ResultSetHandler(handlerResultSets, handleOutputParameters)
- StatmentHandler(prepare, parameterize, batchm, update, query)
总体概括为:
- 拦截执行器的方法
- 拦截参数的处理
- 拦截结果集的处理
- 拦截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 o) {
// 创建target对象的代理对象,目的是将当前拦截器加入到该对象中
return Plugin.wrap(o, this);
}
@Override
public void setProperties(Properties properties) {
// 属性配置
}
}
拦截器配置
@Configuration
@MapperScan("com.dc.mapper")
public class MybatisPlusConfig {
/**
* 分页插件
* @param
* @return
*/
@Bean
public PaginationInterceptor paginationInterceptor() {
return new PaginationInterceptor();
}
@Bean
public MyInterceptor myInterceptor() {
return new MyInterceptor();
}
}
或者通过xml配置,MyBatis-config.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执行的分页的插件,可用作阻断全表更新、删除的操作,注意:该插件仅适用于开发环境,不适用于生产环境
SpringBoot配置:
@Bean
public SqlExplainInterceptor sqlExplainInterceptor() {
SqlExplainInterceptor sqlExplainInterceptor = new SqlExplainInterceptor();
ArrayList<ISqlParser> iSqlParsers = new ArrayList<>();
iSqlParsers.add(new BlockAttackSqlParser());
sqlExplainInterceptor.setSqlParserList(iSqlParsers);
return sqlExplainInterceptor;
}
结果:
org.apache.ibatis.exceptions.PersistenceException:
### Error opening session. Cause: org.apache.ibatis.plugin.PluginException: Could not find method on interface java.util.concurrent.Executor named update. Cause: java.lang.NoSuchMethodException: java.util.concurrent.Executor.update(org.apache.ibatis.mapping.MappedStatement, java.lang.Object)
### Cause: org.apache.ibatis.plugin.PluginException: Could not find method on interface java.util.concurrent.Executor named update. Cause: java.lang.NoSuchMethodException: java.util.concurrent.Executor.update(org.apache.ibatis.mapping.MappedStatement, java.lang.Object)
at org.apache.ibatis.exceptions.ExceptionFactory.wrapException(ExceptionFactory.java:30)
at org.apache.ibatis.session.defaults.DefaultSqlSessionFactory.openSessionFromDataSource(DefaultSqlSessionFactory.java:100)
at org.apache.ibatis.session.defaults.DefaultSqlSessionFactory.openSession(DefaultSqlSessionFactory.java:57)
at org.mybatis.spring.SqlSessionUtils.getSqlSession(SqlSessionUtils.java:98)
at org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke(SqlSessionTemplate.java:428)
at com.sun.proxy.$Proxy58.update(Unknown Source)
at org.mybatis.spring.SqlSessionTemplate.update(SqlSessionTemplate.java:294)
at com.baomidou.mybatisplus.core.override.MybatisMapperMethod.execute(MybatisMapperMethod.java:63)
at com.baomidou.mybatisplus.core.override.MybatisMapperProxy.invoke(MybatisMapperProxy.java:62)
at com.sun.proxy.$Proxy64.update(Unknown Source)
at com.dc.UserMapperTest.testInterceptor(UserMapperTest.java:296)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.springframework.test.context.junit4.statements.RunBeforeTestExecutionCallbacks.evaluate(RunBeforeTestExecutionCallbacks.java:74)
at org.springframework.test.context.junit4.statements.RunAfterTestExecutionCallbacks.evaluate(RunAfterTestExecutionCallbacks.java:84)
at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75)
at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86)
at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:251)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:97)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:190)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:69)
at com.intellij.rt.junit.IdeaTestRunner$Repeater$1.execute(IdeaTestRunner.java:38)
at com.intellij.rt.execution.junit.TestsRepeater.repeat(TestsRepeater.java:11)
at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:35)
at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:235)
at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:54)
Caused by: org.apache.ibatis.plugin.PluginException: Could not find method on interface java.util.concurrent.Executor named update. Cause: java.lang.NoSuchMethodException: java.util.concurrent.Executor.update(org.apache.ibatis.mapping.MappedStatement, java.lang.Object)
at org.apache.ibatis.plugin.Plugin.getSignatureMap(Plugin.java:83)
at org.apache.ibatis.plugin.Plugin.wrap(Plugin.java:44)
at com.dc.interceptor.MyInterceptor.plugin(MyInterceptor.java:31)
at org.apache.ibatis.plugin.InterceptorChain.pluginAll(InterceptorChain.java:31)
at com.baomidou.mybatisplus.core.MybatisConfiguration.newExecutor(MybatisConfiguration.java:168)
at org.apache.ibatis.session.defaults.DefaultSqlSessionFactory.openSessionFromDataSource(DefaultSqlSessionFactory.java:96)
... 41 more
Caused by: java.lang.NoSuchMethodException: java.util.concurrent.Executor.update(org.apache.ibatis.mapping.MappedStatement, java.lang.Object)
at java.lang.Class.getMethod(Class.java:1786)
at org.apache.ibatis.plugin.Plugin.getSignatureMap(Plugin.java:80)
... 46 more
性能分析插件
性能分析拦截器,用于输出每条sql语句及其执行时间,可以设置最大执行时间,超过时间会抛出异常。
该插件只用于开发环境,不建议生产环境使用
配置:
<plugins>
<plugin interceptor="com.baomidou.mybatisplus.extension.plugins.PerformanceInterceptor">
<property name="maxTime" value="100"/>
<property name="format" value="true"/>
</plugin>
</plugins>
结果:
可以看到执行时间为22ms,如果将maxTime设置为1,该操作会直接报错
乐观锁插件
主要使用场景
意图:
当要更新的时候,希望这条记录没有被别人更新
乐观锁实现方式:
- 取出记录时,获取当前version
- 更新时,带上version
- 执行更新时,set version = newVersion where version = oldVersion
- 如果version不对,就更新失败
插件配置
config.xml:
<bean class="com.baomidou.mybatisplus.extension.plugins.OptimisticLockerInterceptor"/>
SpringBoot:
@Bean
public OptimisticLockerInterceptor optimisticLockerInterceptor() {
return new OptimisticLockerInterceptor();
}
注解实体字段
需要为实体字段添加@Version注解
第一步,为表添加version字段,并且设置初始值为1
ALTER TABLE 'user'
ADD COLUMN 'version' int(10) NULL AFTER 'email';
UPDATE 'user' SET 'version' = '1';
第二步,为User实体对象添加version字段,并且添加@Version注解:
@Version
private Integer version;
测试用例:
@Test
public void testUpdate() {
User user = new User();
user.setAge(30);
user.setId(2L);
// 获取到version为1
user.setVersion(1);
int i = this.userMapper.updateById(user);
System.out.println("result = " + i);
}
执行日志:
可以看到,更新的条件中有version条件,并且更新的version为2
如果再次执行,更新则不成功,这样就避免了多人同时更新时导致数据的不一致
特别说明
- 支持的数据类型只有:int,Integer,long,Date, LocalDateTime
- 整数类型下newVersion = oldVersion + 1
- newVersion 会回写到entity中
- 仅支持updateById(id)与update(entity, wrapper)方法
- 在update(entity, wrapper)方法下,wrapper不能复用!!!
sql注入器
在MP中,通过AbstractSqlInjector将BaseMapper中的方法注入到MyBatis容器,这样这些方法才可以正常执行
那如果需要扩展BaseMapper中的方法,又该如何实现?
编写MyBatisMapper
package cn.itcast.mp.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import java.util.List;
public interface MyBaseMapper<T> extends BaseMapper<T> {
List<T> findAll();
}
其他的Mapper都可以继承该Mapper,这样实现了统一的扩展
package cn.itcast.mp.mapper;
import cn.itcast.mp.pojo.User;
public interface UserMapper extends MyBaseMapper<User> {
User findById(Long id);
List<User> findAll();
}
编写MySqlInjector
如果直接继承AbstractSqlInjector的话,原有的BaseMapper中的方法将失效,所以选择继承DefaultSqlInjector进行扩展
public class MySqlInjector extends DefaultSqlInjector {
@Override
public List<AbstractMethod> getMethodList() {
List<AbstractMethod> methodList = super.getMethodList();
methodList.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容器中
spring.xml:
<bean class="com.dc.injector.MySqlInjector"/>
SpringBoot:
/**
* 自定义SQL注入器
*/
@Bean
public MySqlInjector mySqlInjector(){
return new MySqlInjector();
}
测试:
@Test
public void testFindAll() {
List<User> all = userMapper.findAll();
for (User user : all) {
System.out.println(user);
}
}
结果
自动填充功能
有些时候可能会有这样的需求,插入或者更新数据的时候,希望有些字段可以自动填充数据,比如密码,version等。在MP中提供了这样的功能,可以实现自动填充
添加@TableField注解
@TableField(fill = FieldFill.INSERT) // 插入数据时进行填充
private String password;
为password添加自动填充功能,在新增数据时有效
FiledFill提供了多种模式选择:
public enum FieldFill {
/**
* 默认不处理
*/
DEFAULT,
/**
* 插入时填充字段
*/
INSERT,
/**
* 更新时填充字段
*/
UPDATE,
/**
* 插入和更新时填充字段
*/
INSERT_UPDATE
}
编写MyMetaObjectHandler
首先,在User实体类中添加注解
@Data
@AllArgsConstructor
@NoArgsConstructor
@TableName("tb_user")
public class User extends Model<User> {
private Long id;
private String userName;
@TableField(select = false, fill = FieldFill.INSERT)
private String password;
private String name;
private Integer age;
private String email;
@Version
private Integer version;
}
然后编写MyMetaObjectHandler类
public class MyMetaObjectHandler implements MetaObjectHandler {
@Override
public void insertFill(MetaObject metaObject) {
Object password = getFieldValByName("password", metaObject);
if (password == null) {
// 字段为空,进行填充
setFieldValByName("password", "88888888", metaObject);
}
}
@Override
public void updateFill(MetaObject metaObject) {
}
}
spring:最后需要在applicationContext.xml配置文件中配置插件:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!--配置所有properties文件-->
<context:property-placeholder location="classpath:jdbc.properties"></context:property-placeholder>
<!--定义数据源-->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
<property name="maxActive" value="10"/>
<property name="minIdle" value="5"/>
</bean>
<context:component-scan base-package="com.dc.injector"/>
<!--MP提供的SqlSessionFactory,完成了Spring与MP的整合-->
<bean id="sqlSessionFactory" class="com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="typeAliasesPackage" value="com.dc.domain"/>
<property name="plugins">
<array>
<!--分页插件-->
<bean class="com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor"/>
<!--乐观锁插件-->
<bean class="com.baomidou.mybatisplus.extension.plugins.OptimisticLockerInterceptor"/>
</array>
</property>
<!--全局配置-->
<property name="globalConfig" ref="globalConfig"/>
</bean>
<bean id="globalConfig" class="com.baomidou.mybatisplus.core.config.GlobalConfig">
<property name="metaObjectHandler" ref="myMetaObjectHandler"/>
</bean>
<bean class="com.dc.injector.MyMetaObjectHandler" id="myMetaObjectHandler"/>
<bean class="com.dc.injector.MySqlInjector"/>
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.dc.mapper"/>
</bean>
<beans default-autowire="byType"/>
</beans>
SpringBoot:在MyMetaObjectHandler类上添加@Component注解
测试:
@Test
public void testInsertFill() {
User user = new User();
user.setName("关羽");
user.setUserName("guanyu");
user.setAge(30);
user.setEmail("guanyu@dc.cn");
user.setVersion(1);
int insert = userMapper.insert(user);
System.out.println("result = " + insert);
}
效果:
逻辑删除
开发系统时,有时候在实现功能时,删除操作需要实现逻辑删除,所谓逻辑删除就是将数据标记为删除,而并非真正的物理删除(非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;
配置
SpringBoot:
# 逻辑已删除值(默认为 1)
mybatis-plus.global-config.db-config.logic-delete-value=1
# 逻辑未删除值(默认为 0)
mybatis-plus.global-config.db-config.logic-not-delete-value=0
测试
@Test
public void testDeleteById(){
this.userMapper.deleteById(2L);
}
结果:
测试查询:
@Test
public void testSelectById(){
User user = this.userMapper.selectById(2L);
System.out.println(user);
}
结果:
通用枚举
解决了繁琐的配置,让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;
测试:
@Test
public void testInsert1() {
User user = new User();
user.setName("貂蝉");
user.setUserName("diaochan");
user.setAge(20);
user.setEmail("diaochan@dc.cn");
user.setSex(SexEnum.WOMAN);
int insert = userMapper.insert(user);
System.out.println(insert);
}
效果:
查询:
@Test
public void testSelect1() {
User user = userMapper.selectById(2L);
System.out.println(user);
}
结果:
代码生成器
AutoGenerator是MyBatis-Plus的代码生成器,通过AutoGenerator可以快速生成Entity、Mapper、Mapper XML、Service、Controller等各个模块的代码,极大的提升了开发效率
创建工程
pom.xml
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!--mybatis-plus的springboot支持-->
<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.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
代码:
package com.dc;
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.*;
import com.baomidou.mybatisplus.generator.config.po.TableInfo;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
/**
* -----在希望中绽放,在苦难中坚持------
*
* @author 暮辰
*/
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 + "\\smptest\\src\\main\\java");
gc.setAuthor("暮辰");
gc.setOpen(false);
mpg.setGlobalConfig(gc);
// 数据源配置
DataSourceConfig dsc = new DataSourceConfig();
dsc.setUrl("jdbc:mysql://localhost:3306/test?useUnicode=true&useSSL=false&characterEncoding=utf8");
// dsc.setSchemaName("public");
dsc.setDriverName("com.mysql.jdbc.Driver");
dsc.setUsername("root");
dsc.setPassword("root");
mpg.setDataSource(dsc);
// 包配置
PackageConfig pc = new PackageConfig();
pc.setModuleName(scanner("模块名"));
pc.setParent("com.dc.mp");
mpg.setPackageInfo(pc);
// 自定义配置
InjectionConfig cfg = new InjectionConfig() {
@Override
public void initMap() {
// to do nothing
}
};
List<FileOutConfig> focList = new ArrayList<>();
focList.add(new FileOutConfig("\\templates\\mapper.xml.ftl") {
@Override
public String outputFile(TableInfo tableInfo) {
// 自定义输入文件名称
return projectPath + "/smptest/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();
}
}
测试:
代码生成
实体类对象:
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
public class TbUser implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 用户名
*/
private String userName;
/**
* 密码
*/
private String password;
/**
* 姓名
*/
private String name;
/**
* 年龄
*/
private Integer age;
/**
* 邮箱
*/
private String email;
private Integer version;
/**
* 1代表删除,0代表未删除
*/
private Integer deleted;
/**
* 1-男,2-女
*/
private Integer sex;
}
MyBatisX快速开发插件
MyBatisX是一款基于IDEA的快速开发插件,为效率而生。
安装方法:打开 IDEA,进入 File -> Settings -> Plugins -> Browse Repositories,输入 mybatisx 搜索并安装。
功能:
- Java 与 XML 调回跳转
- Mapper 方法自动生成 XML