前言
hi,大家好,这里是Ian,欢迎大家一起来学习java,这篇是我通过b站狂神说的mybatis-plus讲解的视频以及mybatis-plus官方文档,并且自己进行调试总结出来的springboot整合mybatis-plus的笔记,虽然可能会有一些遗漏,欢迎大家查看
文章目录
- 前言
- mybatis-plus整合
- 引入依赖
- 配置日志文件
- 创建一个mybatis-plus整合过的springboot项目
- 自动填充处理
- 乐观锁
- 数据库操作
- 逻辑删除
- 条件构造器Wrapper
- eq 等于 =
- ne 不等于 <>
- gt 大于 >
- ge 大于等于 >=
- lt 小于 <
- between between 值1 and 值2
- notBetween not between 值1 and 值2
- like like'%值%'
- notLike not like'%值%'
- likeLeft like'%值'
- likeRight like'值%'
- isNull is null
- isNotNull is not null
- in in("age",{1,2,3})---->age in (1,2,3)
- notIn notIn("age",{1,2,3})---->age not in (1,2,3)
- insql inSql("id","select id from table where id <3")--> id in (select id from table where id < 3)
- groupBy groupBy("id","name")-->group by (id,name)
- orderByAsc orederByAsc("id","name")-->order by id ASC,name ASC
- orderByDesc orederByDesc("id","name")-->order by id Desc,name Desc
- orderBy orderBy(true, true, "id", "name")-->order by id ASC,name ASC
- or 拼接or eq("id",1).or().eq("name","kun");
- exists exists("select id from table where age = 1")-->exists (select id from table where age = 1)
- notExists notExists("select id from table where age = 1")-->not exists (select id from table where age = 1)
- having having("sum(age) > 10")-->having sum(age) > 10
- queryWrapper
- select select("id","name","age")
- updateWrapper
- set set("name","kun")
- setSql setSql("name='kun'")
- 代码自动生成器
mybatis-plus整合
引入依赖
使用Spring Boot,引入下面这个依赖
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.3</version>
</dependency>
使用ssm的,引入下面这个依赖
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus</artifactId>
<version>3.4.3</version>
</dependency>
配置日志文件
配置日志文件可以让你更直观的查看sql语句
配置日志
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
用来显示sql语句,测试时可以使用
创建一个mybatis-plus整合过的springboot项目
mapper类
@Mapper
public interface UserMapper extends BaseMapper<User> {
//mapper类中不需要有内容,但是需要继承BaseMapper类,并且指定实体类
}
user类
@Component //注册bean
@Data
@AllArgsConstructor
@NoArgsConstructor
@TableName("user")//表名
public class User {
@TableId(type = IdType.ASSIGN_ID)
private int userId;
private String username;
private String password;
private String cellphone;
private int isRoo;
private String address;
}
service类
public interface UserService {
//注册用户
int registUser(User user);
//通过用户名查询用户信息
User queryUserByUsername(String username);
//给用户添加/修改地址
int updateUserAddressByID(String address,int id);
}
serviceimpl类
@Service
public class UserServiceImpl implements UserService {
@Resource
private UserMapper userMapper;
public int registUser(User user) {
return userMapper.insert(user);
}
public User queryUserByUsername(String username) {
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("username",username);//第一个参数是列名,列名必须与数据库列名完全一致,符号大小写的完全一致
return userMapper.selectOne(queryWrapper);
}
public int updateUserAddressByID(String address, int id) {
User user=new User();
user.setUserId(id);
user.setAddress(address);
return userMapper.updateById(user);
}
}
config类
@Configuration
@MapperScan("com.atlizhi.dao")
public class MybatisPlusConfig {
//乐观锁
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());//乐观锁
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));//分页插件
return interceptor;
}
}
自动填充处理
数据库级别的自动填充
表的默认值为CURRENT_TIMESTAMP,并且勾选上更新的按钮每当更新时,会自动更新更新时间
代码别的自动填充
1、在实体类字段属性上添加注解
通过注解进行选择
2、编写一个处理器MyMetaObjectHandler
@Slf4j
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
@Override
public void insertFill(MetaObject metaObject) {
log.info("start insert fill ....");
//createTime就是想要进行填充的字段
this.strictInsertFill(metaObject, "createTime", LocalDateTime.class, LocalDateTime.now()); // 起始版本 3.3.0(推荐使用)
// 或者
this.strictInsertFill(metaObject, "createTime", () -> LocalDateTime.now(), LocalDateTime.class); // 起始版本 3.3.3(推荐)
// 或者
this.fillStrategy(metaObject, "createTime", LocalDateTime.now()); // 也可以使用(3.3.0 该方法有bug)
}
@Override
public void updateFill(MetaObject metaObject) {
log.info("start update fill ....");
this.strictUpdateFill(metaObject, "updateTime", LocalDateTime.class, LocalDateTime.now()); // 起始版本 3.3.0(推荐)
// 或者
this.strictUpdateFill(metaObject, "updateTime", () -> LocalDateTime.now(), LocalDateTime.class); // 起始版本 3.3.3(推荐)
// 或者
this.fillStrategy(metaObject, "updateTime", LocalDateTime.now()); // 也可以使用(3.3.0 该方法有bug)
}
}
乐观锁
1.配置插件
spring xml方式:
<bean class="com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor" id="optimisticLockerInnerInterceptor"/>
<bean id="mybatisPlusInterceptor" class="com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor">
<property name="interceptors">
<list>
<ref bean="optimisticLockerInnerInterceptor"/>
</list>
</property>
spring boot注解方式:
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
return interceptor;
}
2、数据库中添加 verson int 默认为0 列
3、在实体类上verson字段添加注解
@Version
private Integer version;
说明:
支持的数据类型只有:int,Integer,long,Long,Date,Timestamp,LocalDateTime
整数类型下 newVersion = oldVersion + 1
newVersion 会回写到 entity 中
仅支持 updateById(id) 与 update(entity, wrapper) 方法
在 update(entity, wrapper) 方法下, wrapper 不能复用!!!
4、实例
// Spring Boot 方式
@Configuration
@MapperScan("按需修改")
public class MybatisPlusConfig {
/**
* 旧版
*/
@Bean
public OptimisticLockerInterceptor optimisticLockerInterceptor() {
return new OptimisticLockerInterceptor();
}
/**
* 新版
*/
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
mybatisPlusInterceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
return mybatisPlusInterceptor;
}
}
数据库操作
1、普通查询&条件查询 DDL
注意:
wrapper.eq(“name”,“kun”);在使用时,左边的参数代表的是列名,右边的参数代表的是你想要进行比较的值,列名必须与数据库中的列名完全保持一致,一个符号大小写都不能出错
查询全部
List<User> lists = userMapper.selectList(null);//这里参数为querywrapper
//可以通过querywrapper来自定义查询条件
查询单个个体
QueryWrapper<User> wrapper= new QueryWrapper<User>();
wrapper.eq("name","kun");
User user=userMapper.selectOne(wrapper);
通过mapper进行条件查询
HashMap<String,Object> map = new HashMap<>();
//自定义条件查询
map.put("name","kun");//列名 内容
map.put("age",3);
List<User> lists = userMapper.selectByMap(map);//这里查询满足name=坤哥,age=3的条件的集合
分页查询
Page<User> page =new Page<>(1,5);//参数1:当前页 参数2:页面大小
userMapper.selectPage(page,null);//第二个参数是wrapper用来添加条件
List<User> lists=page.getRecords();//getRecords获取当前所有的值
between and区间查询
QueryWrapper<User> wrapper= new QueryWrapper<User>();
wrapper.between("age",10,20);//第一个参数是列名,第二个第三参数是区间范围
Integer count = userMapper.selectCount(wrapper);//查询这个区间的数量
模糊查询
QueryWrapper<User> wrapper= new QueryWrapper<User>();
wrapper.notLike("name","e") //相当于 not like '%e%'
.likeRight("email","t");//相当于 like 't%'
List<Map<String,Object>> maps = userMapper.selectMaps(wrapper);
子查询
QueryWrapper<User> wrapper= new QueryWrapper<User>();
//id在子查询中查出来
wrapper.inSql("id","select id from user where id < 3");
List<Object> objcts=userMapper.selectObjs(wrapper);
排序查询
QueryWrapper<User> wrapper= new QueryWrapper<User>();
//通过id进行排序
wrapper.orderByDesc("id");//参照的列名
List<User> lists=userMapper.selectList(wrapper);
2、数据库更新操作 DML
通过id进行更新
public int updateUserAddressByID(String address, int id) {
User user=new User();
user.setUserId(id);
user.setAddress(address);//通过id更新地址
return userMapper.updateById(user);
}
通过条件构造器作为参数更新
//把名字为rhb的用户年龄更新为18,其他属性不变
UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();
updateWrapper.eq("name","kun");//判断条件 name=rhb
User user = new User();
user.setAge(18);//设置想要更新的属性的新值
userMapper.update(user, updateWrapper);
假设只更新一个字段在使用updateWrapper 的构造器中也需要构造一个实体对象,这样比较麻烦。可以使用updateWrapper的set方法
//只更新一个属性,把名字为rhb的用户年龄更新为18,其他属性不变
UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();
updateWrapper.eq("name","kun").set("age", 18);
userMapper.update(null, updateWrapper);
以上三种更新操作会将实体类的所有属性进行更新,如果有的值是int值且不为null,则会默认改为0.
为此我们可以采用一下更新手段,来进行指定列更新。
public int updateAcq(String eNum, int eAcq, int rid,String eFirstTime) {
UpdateWrapper<EntrustMess> wrapper=new UpdateWrapper<EntrustMess>();
wrapper.eq("e_num",eNum);
wrapper.set("e_acq",eAcq);
wrapper.set("rid",rid);
wrapper.set("e_first_time",eFirstTime);
return entrustMessMapper.update(null,wrapper);
}
3、分页查询的具体操作
1、首先在mybatisPlusConfig中注册分页插件的bean对象
/**
* 分页插件
*/
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
return interceptor;
}
2、然后可以通过下面的方法进行分页查询
@Resource
private EntrustMessMapper entrustMessMapper;
public List<EntrustMess> getPageEntrust(int a) {
Page<EntrustMess> page =new Page<EntrustMess>(a,4);//参数1:当前页 参数2:页面大小
QueryWrapper queryWrapper = new QueryWrapper();
queryWrapper.eq("e_acq",0);//用来限定条件,如果不需要限定的话,下面这个queryWrapper参数可以填null。
entrustMessMapper.selectPage(page,queryWrapper);
List<EntrustMess> lists=page.getRecords();//getRecords获取当前所有的值
return lists;
}
根据id删除记录
int result = userMapper.deleteById(8L);
批量删除
int result = userMapper.deleteBatchIds(Arrays.asList(8, 9, 10));
简单的map条件查询删除
HashMap<String, Object> map = new HashMap<>();
map.put("name", "Helen");
map.put("age", 18);
int result = userMapper.deleteByMap(map);
简单的wrapper条件查询删除
QueryWrapper<User> wrapper= new QueryWrapper<User>();
wrapper.eq("name","kun");
int result=userMapper.delete(wrapper);
逻辑删除
1、在数据库中添加一个deleted字段 默认值为0
2、给实体类添加一个deleted字段 并且添加上注解 @TableLogic
@TableLogic
private int deleted;
3、配置com.baomidou.mybatisplus.core.config.GlobalConfig$DbConfig
mybatis-plus:
global-config:
db-config:
logic-delete-field: flag # 全局逻辑删除的实体字段名(since 3.3.0,配置后可以忽略不配置步骤2)
logic-delete-value: 1 # 逻辑已删除值(默认为 1)
logic-not-delete-value: 0 # 逻辑未删除值(默认为 0)
当我们进行删除时,会执行更新操作,然后将deleted字段变为1
当我们进行查询时,会自动添加一个deleted=0的操作
条件构造器Wrapper
-
eq 等于 =
-
ne 不等于 <>
-
gt 大于 >
-
ge 大于等于 >=
-
lt 小于 <
-
between between 值1 and 值2
-
notBetween not between 值1 and 值2
-
like like’%值%’
-
notLike not like’%值%’
-
likeLeft like’%值’
-
likeRight like’值%’
-
isNull is null
-
isNotNull is not null
-
in in(“age”,{1,2,3})---->age in (1,2,3)
-
notIn notIn(“age”,{1,2,3})---->age not in (1,2,3)
-
insql inSql(“id”,“select id from table where id ❤️”)–> id in (select id from table where id < 3)
-
groupBy groupBy(“id”,“name”)–>group by (id,name)
-
orderByAsc orederByAsc(“id”,“name”)–>order by id ASC,name ASC
-
orderByDesc orederByDesc(“id”,“name”)–>order by id Desc,name Desc
-
orderBy orderBy(true, true, “id”, “name”)–>order by id ASC,name ASC
-
or 拼接or eq(“id”,1).or().eq(“name”,“kun”);
-
exists exists(“select id from table where age = 1”)–>exists (select id from table where age = 1)
-
notExists notExists(“select id from table where age = 1”)–>not exists (select id from table where age = 1)
-
having having(“sum(age) > 10”)–>having sum(age) > 10
queryWrapper
updateWrapper
代码自动生成器
1、引入依赖
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>3.4.1</version>
</dependency>
引入模板依赖 注意!如果您选择了非默认引擎,需要在 AutoGenerator 中 设置模板引擎。
Velocity(默认)
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity-engine-core</artifactId>
<version>2.3</version>
</dependency>
Freemarker:
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.31</version>
</dependency>
Beetl:
<dependency>
<groupId>com.ibeetl</groupId>
<artifactId>beetl</artifactId>
<version>3.3.2.RELEASE</version>
</dependency>
AutoGenerator generator = new AutoGenerator();
// set freemarker engine
generator.setTemplateEngine(new FreemarkerTemplateEngine());
// set beetl engine
generator.setTemplateEngine(new BeetlTemplateEngine());
// set custom engine (reference class is your custom engine class)
generator.setTemplateEngine(new CustomTemplateEngine());
// other config
...
2、配置 GlobalConfig
GlobalConfig globalConfig = new GlobalConfig();
globalConfig.setOutputDir(System.getProperty("user.dir") + "/src/main/java");
globalConfig.setAuthor("jobob");
globalConfig.setOpen(false);
3、配置 DataSourceConfig
DataSourceConfig dataSourceConfig = new DataSourceConfig();
dataSourceConfig.setUrl("jdbc:mysql://localhost:3306/ant?useUnicode=true&useSSL=false&characterEncoding=utf8");
dataSourceConfig.setDriverName("com.mysql.jdbc.Driver");
dataSourceConfig.setUsername("root");
dataSourceConfig.setPassword("password");
4、包的配置
5、策略配置
自定义模板引擎
请继承类 com.baomidou.mybatisplus.generator.engine.AbstractTemplateEngine
//指定自定义模板路径, 位置:/resources/templates/entity2.java.ftl(或者是.vm)
//注意不要带上.ftl(或者是.vm), 会根据使用的模板引擎自动识别
TemplateConfig templateConfig = new TemplateConfig()
.setEntity("templates/entity2.java");
AutoGenerator mpg = new AutoGenerator();
//配置自定义模板
mpg.setTemplate(templateConfig);
自定义属性注入
InjectionConfig injectionConfig = new InjectionConfig() {
//自定义属性注入:abc
//在.ftl(或者是.vm)模板中,通过${cfg.abc}获取属性
@Override
public void initMap() {
Map<String, Object> map = new HashMap<>();
map.put("abc", this.getConfig().getGlobalConfig().getAuthor() + "-mp");
this.setMap(map);
}
};
AutoGenerator mpg = new AutoGenerator();
//配置自定义属性注入
mpg.setCfg(injectionConfig);
entity2.java.ftl
自定义属性注入abc=${cfg.abc}
entity2.java.vm
自定义属性注入abc=$!{cfg.abc}
整体代码
// 演示例子,执行 main 方法控制台输入模块表名回车自动生成对应项目目录中
public class CodeGenerator {
public static void main(String[] args) {
// 代码生成器
AutoGenerator mpg = new AutoGenerator();
// set beetl engine//修改模板
//mpg.setTemplateEngine(new BeetlTemplateEngine());
// 全局配置
GlobalConfig gc = new GlobalConfig();
String projectPath = System.getProperty("user.dir");
gc.setOutputDir(projectPath + "/src/main/java");
gc.setAuthor("kun");
gc.setOpen(false);
gc.setFileOverride(false);
gc.setServiceName("%sService");//去Service的i前缀
gc.setIdType(IdType.ID_WORKER);
gc.setDateType(DateType.ONLY_DATE);
gc.setSwagger2(true);
mpg.setGlobalConfig(gc);
// 数据源配置
DataSourceConfig dsc = new DataSourceConfig();
dsc.setUrl("jdbc:mysql://localhost:3306/roo_delivery?useUnicode=true&useSSL=false&characterEncoding=utf8");
dsc.setDriverName("com.mysql.cj.jdbc.Driver");
dsc.setUsername("root");
dsc.setPassword("111222");
dsc.setDbType(DbType.MYSQL);
mpg.setDataSource(dsc);
// 包配置
PackageConfig pc = new PackageConfig();
//pc.setModuleName("blob");//不需要
pc.setParent("com.atkunge");
pc.setEntity("entity");
pc.setMapper("mapper");
pc.setService("service");
pc.setController("controller");
mpg.setPackageInfo(pc);
// 配置模板
TemplateConfig templateConfig = new TemplateConfig();
// 配置自定义输出模板
//指定自定义模板路径,注意不要带上.ftl/.vm, 会根据使用的模板引擎自动识别
// templateConfig.setEntity("templates/entity2.java");
// templateConfig.setService();
// templateConfig.setController();
templateConfig.setXml(null);
mpg.setTemplate(templateConfig);
// 策略配置
StrategyConfig strategy = new StrategyConfig();
strategy.setInclude("user");//可以有多个,与数据库表名相照应
strategy.setNaming(NamingStrategy.underline_to_camel);
strategy.setColumnNaming(NamingStrategy.underline_to_camel);
strategy.setEntityLombokModel(true);
strategy.setLogicDeleteFieldName("deleted");
strategy.setRestControllerStyle(false);
strategy.setControllerMappingHyphenStyle(true);
strategy.setTablePrefix(pc.getModuleName() + "_");
//乐观锁
strategy.setVersionFieldName("version");
mpg.setStrategy(strategy);
mpg.execute();
}
}