Mybatiplus是mybatis增强工具包,制作增强,不做改变。
官网:http://mp.baomidou.com
注解:
//@TableName 实体类的类名和数据库表名不一致
//@TableId 实体类的主键名称和表中主键名称不一致,和主键策略,type是主键策略。
//@TableField 实体类中的成员名称和表中字段名称不一致,value是数据库字段名,fill是自动插入、更新等,exist表示存不存在(如果数据库没有把它设置为false,就不会出现在数据库语句中)
javaBean中的成员变量的类型使用时尽量使用包装类型(如Integer、String),这样当不存在的时候会返回null,有利于判断。
.propertises文件相关配置:https://blog.csdn.net/weixin_42873160/article/details/94622555
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.url=jdbc:mysql://localhost:3306/school?serverTimezone=Hongkong&useUnicode=true&characterEncoding=utf8
spring.datasource.username=root
spring.datasource.password=password
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.dbcp2.min-idle=5
spring.datasource.dbcp2.initial-size=5
spring.datasource.dbcp2.max-total=5
spring.datasource.dbcp2.max-wait-millis=200
#mybatis-plus
# 如果是放在src/main/java目录下 classpath:/com/yourpackage/*/mapper/*Mapper.xml
# 如果是放在resource目录 classpath:/mapper/*Mapper.xml
mybatis-plus.mapper-locations=classpath:/com/springboot/study/mapper/*Mapper.xml
#实体扫描,多个package用逗号或者分号分隔
mybatis-plus.type-aliases-package=com.springboot.study.entity
#主键类型 0:"数据库ID自增", 1:"用户输入ID",2:"全局唯一ID (数字类型唯一ID)", 3:"全局唯一ID UUID";
mybatis-plus.global-config.id-type=3
#字段策略 0:"忽略判断",1:"非 NULL 判断"),2:"非空判断"
mybatis-plus.global-config.field-strategy=2
#驼峰下划线转换
mybatis-plus.global-config.db-column-underline=true
#mp2.3+ 全局表前缀 mp_
#mybatis-plus.global.table-prefix: mp_
#刷新mapper 调试神器
mybatis-plus.global-config.refresh-mapper=true
#数据库大写下划线转换
mybatis-plus.global-config.capital-mode=true
# Sequence序列接口实现类配置
mybatis-plus.global-config.key-generator=com.baomidou.mybatisplus.incrementer.OracleKeyGenerator
#逻辑删除配置(下面3个配置)
mybatis-plus.global-config.logic-delete-value=1
mybatis-plus.global-config.logic-not-delete-value=0
mybatis-plus.global-config.sql-injector=com.baomidou.springboot.MyMetaObjectHandler
#配置返回数据库(column下划线命名&&返回java实体是驼峰命名),自动匹配无需as(没开启这个,SQL需要写as: select user_id as userId)
mybatis-plus.configuration.map-underscore-to-camel-case=true
***在po m.xml中引入,mybatis和mybatis-spring不需要加入,mybatisplus会自动维护。
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.3.1.tmp</version>
</dependency>
***创建mybatisplus的配置文件:
可以用xml文件,也可以使用Java类配置。
****Mapper层CRUD******
***插入
一定更要在id前面加一个主键策略,否则数据库表中id会乱。
@TableId(type=IdType.AUTO)
private Long id;
*****
@RequestMapping("/add")
public R insertUser() {
User user=new User();
user.setId(null);
user.setAge(18);
user.setName("lmabo");
user.setToken("mytoken");
Integer result = userMapper.insert(user);
//获取新插入数据字数据库中的主键值
Long i=user.getId();
System.out.println("新插入的主键值"+i);
return R.ok().data("add",result);
}
***更新
//更新,根据id修改user对象
@RequestMapping("/updatebyid")
public R updateUser() {
User user=new User();
user.setId(3L);
user.setAge(18);
user.setName("lambo001");
user.setToken("mytoken");
Integer result = userMapper.updateById(user);
return R.ok().data("updatebyid",result);
}
***查询
//查询,通过id
@RequestMapping("/selectbyid")
public R selectUser0() {
User user = userMapper.selectById(6);
return R.ok().data("selectById",user);
}
//查询,通过id
@RequestMapping("/selectall")
public R selectUser01() {
List<User> users = userMapper.selectList(null);
return R.ok().data("selectById",users);
}
// //通过多个列查询
// @RequestMapping("/selectbycolumns")
// public R selectUser02() {
//
// User user=new User();
// user.setId(3L);
// user.setAge(18);
// User resuser = userMapper.selectOne(queryWrapper)
// return R.ok().data("selectbycolumns",resuser);
// }
//根据ID批量查询
@RequestMapping("/selectBatchIds")
public R selectUser03() {
List<Integer> idlist=new ArrayList<>();
idlist.add(3);
idlist.add(4);
List<User> userlist = userMapper.selectBatchIds(idlist);
return R.ok().data("selectById",userlist);
}
//通过map查询
@RequestMapping("/selectByMap")
public R selectUser04() {
Map<String,Object> columnMap=new HashMap<>();
columnMap.put("name", "lambo001");
List<User> userlist = userMapper.selectByMap(columnMap);
return R.ok().data("selectById",userlist);
}
//通过page查询
@RequestMapping("/selectpage")
public R selectUser05() {
Page<User> page= new Page<User>(1,5);
Page<User> usepage=userMapper.selectPage(page, null);
long current=usepage.getCurrent();
long pages=usepage.getPages();
long total=usepage.getTotal();
long size=usepage.getSize();
System.out.println(total);
List<User>users=usepage.getRecords();
users.forEach(System.out::println);
return R.ok().data("selectpage",users);
}
***删除
/**
* 根据id删除
* **/
@RequestMapping("/deletebyid")
public R deletebyid() {
int result=userMapper.deleteById(2L);
System.out.println(result);
return R.ok().data("deletebyid",result);
}
/**
* 批量删除
* **/
@RequestMapping("/deletebatch")
public R deleteBatch() {
int result=userMapper.deleteBatchIds(Arrays.asList(1,2,3));
System.out.println(result);
return R.ok().data("deletebatch",result);
}
/**
* 简单条件 查询删除
* */
@RequestMapping("/deletebymap")
public R DeleteByMap() {
HashMap<String,Object>map=new HashMap<>();
map.put("name","lambo");
map.put("age", 35);
int result=userMapper.deleteByMap(map);
System.out.println(result);
return R.ok().data("deletebymap",result);
}
***mybatis全局策略配置:
下划线和驼峰命名对应(如:数据库中a_c字段可以对应java类中的aC属性;)
可以全局配置主键的策略;
全局表前缀配置;
***mybatisplus启动注入sql的原理:
mybatis的执行流程:
***条件构造器:
mybatisplus通过QueryWrapper(以前是EntityWrapper)封装一个查询条件构造器,后者用condition来让用户自由的构建查询条件。
用的是数据库字段,不是java属性;
QueryWrapper(以前是EntityWrapper)、updateWrapper继承Wrapper;
语法糖是计算机语言中添加的某种语法,这种语法对语言的功能没有影响,可以避免出错机会,帮助开发者更好的调试。
//删除
public void testone1() {
QueryWrapper<User> queryWrapper=new QueryWrapper<>();
queryWrapper.isNull("name").ge("age",23).isNotNull("phoneNum");
int result=userMapper.delete(queryWrapper);
}
//查询
public void testselectOne2() {
QueryWrapper<User> queryWrapper=new QueryWrapper<>();
queryWrapper.eq("name", "tom");
User user=userMapper.selectOne(queryWrapper);
}
//selectPage
public R selectPage() {
Page<User> page= new Page<User>(1,5);
QueryWrapper<User> queryWrapper=new QueryWrapper<User>();
queryWrapper.between("id", 1,3).eq("age", 18);
Page<User> pag=userMapper.selectPage(page, queryWrapper);
List<User> res= pag.getRecords();
return R.ok().data("data", res);
}
public R testselectList4() {
QueryWrapper<User> queryWrapper=new QueryWrapper<>();
Map<String,Object> map=new HashMap<>();
map.put("id",22);
map.put("name","jack");
map.put("age",38);
queryWrapper.allEq(map);
List<User> users=userMapper.selectList(queryWrapper);
return R.ok().data("data",users);
}
public R testselectList04() {
QueryWrapper<User> queryWrapper=new QueryWrapper<>();
queryWrapper.eq("age", 18).orderByAsc("age");
List<User> users=userMapper.selectList(queryWrapper);
return R.ok().data("data",users);
}
public R testselectMap5() {
QueryWrapper<User> queryWrapper=new QueryWrapper<>();
queryWrapper.notLike("id",22).
likeRight("name","l");
List<Map<String,Object>> users=userMapper.selectMaps(queryWrapper);
return R.ok().data("data",users);
}
public R testselectObjects6() {
QueryWrapper<User> queryWrapper=new QueryWrapper<>();
queryWrapper.inSql("id", "select id from user where id>11");
List<Object> users=userMapper.selectObjs(queryWrapper);
return R.ok().data("data",users);
}
// //这个貌似现在不用了
// public R conditionselect() {
// Page<User> page= new Page<User>(1,5);
// Page<User> users=userMapper.selectPage(page,Condition.create().between("age",1,20));
// return R.ok().data("data",users);
//
// }
//更新
public R testUpdates7() {
//要修改的值
User user=new User();
user.setAge(20);
user.setName("lamboo");
//修改的条件
UpdateWrapper<User> updateWrapper=new UpdateWrapper<>();
updateWrapper.notLike("id",22).or().
likeRight("name","l");
updateWrapper.notLike("id",22).or(
i->i.eq("name","l").ne("age",20));
int result=userMapper.update(user,updateWrapper);
return R.ok().data("data",result);
}
public R testselectSet8() {
User user=new User();
user.setAge(20);
user.setName("lamboo");
//修改的条件
UpdateWrapper<User> updateWrapper=new UpdateWrapper<>();
updateWrapper.like("name","name").set("name","lisi").setSql("phoneNum='1333333'");
int result=userMapper.update(user,updateWrapper);
return R.ok().data("data",result);
}
***ActiveRecord活动记录
一种领域模型模式,特点是一个模型对应关系型数据库中的一个表,一个模型类的一个实例对应对应表中的一行记录。
/*
* AR操作
* */
//插入
public R ar1() {
User user=new User();
user.setAge(20);
user.setName("lamboo");
boolean res=user.insert();
return R.ok().data("data",res);
}
//update
public R ar2() {
User user=new User();
user.setId(3L);
user.setAge(20);
user.setName("lamboo");
boolean res=user.updateById();
return R.ok().data("data",res);
}
//查询
public R ar3() {
User user=new User();
User res=user.selectById(3L);
return R.ok().data("data",res);
}
public R ar4() {
User user=new User();
user.setId(3L);
User res=user.selectById();
return R.ok().data("data",res);
}
//查询全表
public R ar5() {
User user=new User();
List<User> res=user.selectAll();
return R.ok().data("data",res);
}
public R ar6() {
User user=new User();
QueryWrapper<User> queryWrapper=new QueryWrapper<User>();
queryWrapper.between("id", 1,3).eq("age", 18);
List<User> res=user.selectList(queryWrapper);
return R.ok().data("data",res);
}
//查询统计
public R ar7() {
User user=new User();
QueryWrapper<User> queryWrapper=new QueryWrapper<User>();
queryWrapper.between("id", 1,3).eq("age", 18);
Integer res=user.selectCount(queryWrapper);
return R.ok().data("data",res);
}
//分页的复杂操作
public R ar11() {
User user=new User();
Page<User> page= new Page<User>(1,5);
QueryWrapper<User> queryWrapper=new QueryWrapper<User>();
queryWrapper.between("id", 1,3).eq("age", 18);
Page<User> pag=user.selectPage(page, queryWrapper);
List<User> res= pag.getRecords();
return R.ok().data("data",res);
}
//删除
public R ar8() {
User user=new User();
user.setId(3L);
boolean res=user.deleteById();
return R.ok().data("data",res);
}
public R ar9() {
User user=new User();
boolean res=user.deleteById(3);
return R.ok().data("data",res);
}
public R ar10() {
User user=new User();
QueryWrapper<User> queryWrapper=new QueryWrapper<User>();
queryWrapper.between("id", 1,3).eq("age", 18);
boolean res=user.delete(queryWrapper);
return R.ok().data("data",res);
}
***代码生成器:https://mybatis.plus/guide/generator.html#编写配置
mybatisplus的代码生成器是基于java代码生成的,mybatis 的代码生成器MBG是基于xml文件进行代码生成的。
mybaitis代码生成器可生成:实体类、mapper接口、mapper映射文件;
mybaitisplus代码生成器可生成:实体类(可以选择是否支持AR)、mapper接口、mapper映射文件、service层、controller层;
表及字段命名的策略选择,建议数据库表明和表字段名采用驼峰命名,如果使用下划线命名,需要开启下划线开关。如果表名和字段名方式不一致,需要用注解。
代码生成器需要加入的依赖:mybatisplus生成器默认是用的是Apache的Velocity模板,淡然也可以更改为其他模版,如freemarker。
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>3.3.1.tmp</version>
</dependency>
<!-- 添加 模板引擎-->
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity-engine-core</artifactId>
<version>2.1</version>
</dependency>
//1.全局配置
//2.数据源配置
//3.策略配置
//4.包名配置
//5.整合配置
//6.执行
以下只是参照,引入GlobalConfig包的时候要注意,选择generator的那个;
AutoGenerator mpg = new AutoGenerator();
// 全局配置
GlobalConfig gc = new GlobalConfig();
gc.setOutputDir("D:\\generation");//输出文件路径
gc.setFileOverride(true); // 是否文件覆盖
gc.setActiveRecord(false);// 不需要ActiveRecord(实体类继承Model)特性的请改为false
gc.setEnableCache(false);// XML 二级缓存
gc.setBaseResultMap(true);// XML ResultMap
gc.setBaseColumnList(true);// XML ColumnList
gc.setAuthor("lizhan");// 作者
// 自定义文件命名,注意 %s 会自动填充表实体属性!
gc.setControllerName("%sController");
// 默认service接口名IXXXService 自定义指定之后就不会用I开头了
gc.setServiceName("%sService");
gc.setServiceImplName("%sServiceImpl");
gc.setMapperName("%sMapper");
gc.setXmlName("%sMapper");
mpg.setGlobalConfig(gc);
// 数据源配置
DataSourceConfig dsc = new DataSourceConfig();
dsc.setDbType(DbType.MYSQL);
dsc.setDriverName("com.mysql.cj.jdbc.Driver");
dsc.setUsername("xxx");
dsc.setPassword("xxx");
dsc.setUrl("jdbc:mysql://localhost:3306/xxx");
mpg.setDataSource(dsc);
// 策略配置
StrategyConfig strategy = new StrategyConfig();
// strategy.setTablePrefix(new String[] { "sys_" });// 此处可以修改为您的表前缀
strategy.setNaming(NamingStrategy.underline_to_camel);// 表名生成策略(下划线转驼峰)
strategy.setInclude("user"); // 需要生成的表名
strategy.setSuperServiceClass(null);
strategy.setSuperServiceImplClass(null);
strategy.setSuperMapperClass(null);
mpg.setStrategy(strategy);
// 包配置
PackageConfig pc = new PackageConfig();
pc.setParent("com.xxx");
pc.setController("controller");
pc.setService("service");
pc.setServiceImpl("impl");
pc.setMapper("mapper");
pc.setEntity("entity");
pc.setXml("xml");
mpg.setPackageInfo(pc);
// 执行生成
mpg.execute();
****IService
在ServiceImpl中已经完成了mapper对象的注入,可以直接使用CRUD;
@Service
public interface TeacherService extends IService<Teacher>
public class TeacherServiceImpl extends ServiceImpl implements TeacherService
***插件
mybatis插件机制:可以做拦截四大对象,Excutor,StatementHandler,ParameterHandler,ResultSetHandler;
插件原理:四大对象每个在创建的时候,都会执行interceptorChain.pluginAll();会经过每个插件对象的plugin()方法,
目的是为当前的四大对象创建代理对象,通过代理来执行;
分页插件:
在MybatisPlusConfig配置文件中实现以下的方法:
@Configuration
@EnableTransactionManagement
@MapperScan("com.example.demo.mapper")
@Api("配置")
public class MybatisPlusConfig { }
/**
* 分页插件
* */
@ApiOperation(value="分页插件")
@Bean
public PaginationInterceptor paginationInterceptor() {
PaginationInterceptor paginationInterceptor = new PaginationInterceptor();
// 设置请求的页面大于最大页后操作, true调回到首页,false 继续请求 默认false
// paginationInterceptor.setOverflow(false);
// 设置最大单页限制数量,默认 500 条,-1 不受限制
// paginationInterceptor.setLimit(500);
// 开启 count 的 join 优化,只针对部分 left join
paginationInterceptor.setCountSqlParser(new JsqlParserCountOptimize(true));
return paginationInterceptor;
}
乐观锁插件:@Version用于注解实体字段,必须要有。在数据库表中要有version这个字段。
@Version
private Integer version;
@Bean
public OptimisticLockerInterceptor optimisticLockerInterceptor() {
return new OptimisticLockerInterceptor();
}
****执行效率插件
/**
* sql执行效率插件
* */
@Bean
@Profile({"dev","test"})
public PerformanceMonitorInterceptor performanceMonitorInterceptor() {
PerformanceMonitorInterceptor p= new PerformanceMonitorInterceptor();
return p;
}
***快速开发插件MybatisX
MybatisX 是一款基于 IDEA 的快速开发插件,为效率而生。
安装方法:打开 IDEA,进入 File -> Settings -> Plugins -> Browse Repositories,输入 mybatisx
搜索并安装
可实现java和xml的跳转;根据mapper接口中的方法自动生成xml;
***mybatisplus中sql注入器https://www.cnblogs.com/liuyangfirst/p/9744011.html、https://blog.csdn.net/Fire_Sky_Ho/article/details/104110352
*根据DefaultSqlInjector自定义各种sql注入;
/*1.在Mapper接口中定义相关的crud方法
*2.自定义一个继承AbstractMethod的类,重写相关的方法,在方法中实现自定义的sql语句。
*3.创建注入器,新建一个类继承DefaultSqlInjector,实现,mapper接口中要注入的sql方法
*4.在mybatisplus全局策略配置中配置自定义注入器。
*5.直接调用第一步在Mapper中注入的方法;
**/
import org.springframework.stereotype.Repository;
/*这个是数据库操作的类,操作的是User实体类对应的数据库表*/
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.example.entity.User;
@Repository
public interface UserMapper extends BaseMapper<User>{
/**
* 自定义deleteAll操作
* 在启动时 就自动注入,和BaseMapper里面的其他方法一样
*/
int deleteAll();
}
***
import com.baomidou.mybatisplus.core.injector.AbstractMethod;
import com.baomidou.mybatisplus.core.metadata.TableInfo;
//创建定义方法的类
public class DeleteAll extends AbstractMethod {
@Override
public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
/* 执行 SQL ,动态 SQL 参考类 SqlMethod */
String sql = "select age from " + tableInfo.getTableName();
/* mapper 接口方法名一致 */
String method = "deleteAll";
SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass);
return this.addDeleteMappedStatement(mapperClass, method, sqlSource);
}
}
**
mport com.baomidou.mybatisplus.core.injector.AbstractMethod;
import com.baomidou.mybatisplus.core.injector.DefaultSqlInjector;
//创建注入器
@Component
public class Mysqlinject extends DefaultSqlInjector{
/**
* 如果只需增加方法,保留MP自带方法
* 可以super.getMethodList() 再add
*/
@Override
public List<AbstractMethod> getMethodList(Class<?> mapperClass) {
List<AbstractMethod> methodList = super.getMethodList(mapperClass);
methodList.add(new DeleteAll());
return methodList;
}
}
***
配置sql注入器
***调用mapper中定义的方法;
*逻辑删除:不是真正的删除,把被删除的这条数据中逻辑删除字段logic_flag置为删除状态,其实只是更新了logic_flag这个字段的值;
在数据库表中要有一个逻辑删除字段如logic_flag;
在java类中逻辑删除对应字段的属性上添加@TableLogic注解;
配置全局删除值,
*
***公共字段自动填充
更新插入都会自动填充
@TableField(value="update_time",fill = FieldFill.INSERT_UPDATE)
private Date updateTime;
//插入自动填充
@TableField(value="create_time",fill = FieldFill.INSERT)
private Date createTime;
//自定义字段自动填充处理器
@Component
public class MyMetaObjectHandler implements MetaObjectHandler{
@Override
public void insertFill(MetaObject metaObject) {
//获取需要被填充的字段的值
Object fieldValue=getFieldValByName("createTime",metaObject);
if(fieldValue==null) {
// 插入时自动更新的字段,这里面的第二个参数new Date()就是自动填充的值。
this.setFieldValByName("createTime", new Date(), metaObject);
this.setFieldValByName("updateTime", new Date(), metaObject);
}
}
@Override
public void updateFill(MetaObject metaObject) {
//获取需要被填充的字段的值
Object fieldValue=getFieldValByName("createTime",metaObject);
if(fieldValue==null) {
this.setFieldValByName("updateTime", new Date(), metaObject);
}
}
}
***Oracle sequence主键策略
mysql支持主键自增,
Oracle不支持主键自增,通过序列Sequence;
因为授权的问题,无法从maven仓库中下载Orcale的驱动,需要从官方下载;
类之前添加注解@KeySequence(value="seq_user",clazz="Integer.class")
//主键策略@TableId(type=IdType.INSERT),或者作全局配置,在全局策略中注入;
可将@KeySequence定义在父类中,可实现多个子类对应多个表;