环境:spring boot +maven+MySQL
一、Mybatis-plus简介:
Mybatis vs JPA
Mybatis优势:
1)SQL语句可以自由控制,更灵活,性能更高
2)SQL与代码分离,易于阅读和维护
3)提供XML标签,支持编写动态SQL语句
劣势:
1)简单的CRUD操作还得写SQL语句
2)XML中有大量的SQL要维护
3)MyBatis自身功能很有限,但支持Plugin
JPA优势:
1)JPA移植性比较好(JPQL)
2)提供了很多CRUD方法、开发效率高
3)对象化程度更高
Mybatis-Plus就是解决Mybatis中的一些缺点。
Mybatis-Plus(简称MP)是一个 Mybatis 的增强工具,在 Mybatis 的基础上只做增强不做改变,为简化开发、提高效率而生。这是官方给的定义,关于mybatis-plus的更多介绍及特性,可以参考mybatis-plus官网。那么它是怎么增强的呢?其实就是它已经封装好了一些crud方法,我们不需要再写xml了,直接调用这些方法就行,就类似于JPA。
二、MyBatis-Plus特性
1、无侵入、损耗小、强大的CRUD功能
2、支持Lambda形式调用、支持多种数据库
3、支持主键自动生成、支持ActiveRecord模式
4、支持自定义全局通用操作、支持关键词自动转义
5、内置强大的代码生成器、内置分页插件、内置性能分析插件
6、内置全局拦截插件、内置sql注入剥离器
三、安装及配置
引入依赖
Maven:
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.2.0</version>
</dependency>
application.yml:
spring:
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://192.168.0.1:3306/hfs?useUnicode=true&characterEncoding=utf-8
username: #
password: #
logging:
level:
root: warn
org.hthc.db.dao: trace
配置 MapperScan 注解
@SpringBootApplication
@MapperScan("com.baomidou.mybatisplus.samples.quickstart.mapper")//mapper包名
public class Application {
public static void main(String[] args) {
SpringApplication.run(QuickStartApplication.class, args);
}
}
entity 略
mapper 略
四、常用注解
@TableName
描述:表名注解
@TableId
描述:主键注解
@TableFieId
描述:字段注解(非主键)
排除非表字段的三种方式:
//1、加上关键字 transient 不参与序列号过程
private transient String test;
//2、标识为静态变量,可参与序列号过程
private static String test;
//3、使用@TableField(exist=false) 注解
@TableField(exist=false)
private String test;
五、MP的CRUD
查询所有用户
@Autowired
private UserMapper userMapper; //注入userMapper
@Test //测试方法
void selectAll() {
List<sysUser> list = userMapper.selectList(null); //查询所有用户
list.forEach(System.out::println);
}
1、insert操作
实体插入
@Autowired
private UserMapper userMapper;
@Test
public void insert(){
User user = new User();
user.setName("张三")
user.setAge(18);
int rows = userMapper.insert(user);
System.out.println("影响记录数:"+rows);
}
2、select操作
普通查询
1)根据ID查询
User user = userMapper.selectById(24);
2) 根据ID批量查询
List<Int> idsList = Arrays.asList(11,23,52,36);
List<User> userList = userMapper.selectBatchIds(idsList);
userList.forEach(System.out::println);
3) 使用Map根据条件查询返回多条数据
Map<String, Object> columnMap = new HashMap<String, Object>();
columnMap.put("name","张三");
columnMap.put("age",25);
//相当于 where name="张三" and age=25 map的键相当于数据表中的列
List<User> userList = userMapper.selectByMap(columnMap);
条件构造器查询
构造器创建:
1、QueryWrapper<User> queryWrapper = new QueryWrapper<User>();
2、QueryWrapper<User> query = Wrappers.<User>query();
1、名字中包含雨并且年龄小于40
name like '%雨%' and age<40
QueryWrapper<User> queryWrapper = new QueryWrapper<User>();
queryWrapper.like("name","雨").lt("age",40);
List<User> userList = userMapper.selectList(queryWrapper );
2、名字中包含雨并且年龄大于等于20且小于等于40并且Email不为空
//name like '%雨%' and age between 20 and 40 and email is not null
queryWrapper.like("name","雨").between("age",20, 40).isNotNull("email")
3、名字为王姓或者年龄大于等于25,按照年龄降序排序,年龄相同按照ID升序排序
//name like '王%' or age >= 40 order by age desc, id asc
queryWrapper.likeRight("name","王").or().ge("age", 25).orderByDesc("age").orderByAsc("id");
4、创建日期为2019年2月14日并且直属上级为名字为王姓
apply(String applySql, Object... params)
apply("date_format(create_time,'%Y-%m-%d') = '2019-02-14' ") 有注入风险
apply("date_format(create_time,'%Y-%m-%d') = {0}","2019-02-14") 无注入风险
//date_format(create_time,'%Y-%m-%d') and manager_id in (select id from user where name like '王%')
queryWrapper.apply("date_format(create_time,'%Y-%m-%d') = {0}","2019-02-14").inSql("manager_id", "select id from user where name like '王%'");
5、名字为王姓并且(年龄小于40或邮箱不为空)
//name like '王%' and (age<40 or email is not null)
queryWrapper.likeRight("name", "王").and(wq->wq.lt("age").or().isNotNull("email"));
6、名字为王姓或者(年龄小于40并且年龄大于20并且邮箱不为空)
//name like '王%' or (age<40 and age >20 and email is not null)
queryWrapper.likeRight("name", "王").or(wq->wq.lt("age",40).gt("age",20).isNotNull("email"));
7、(年龄小于40或邮箱不为空) 并且名字为王姓
//(age<40 or email is not null) and name like '%王'
queryWrapper.nested(wq->wq.lt("age", 40).or().isNotNull("email")).likeRight("name","王");
8、年龄为30、31、34、35
//age in (30、31、34、35)
queryWrapper.in("age",Arrays.asList(30,31,34,35))
9、只返回满足条件的其中一条语句即可
//limit 1
queryWrapper.in("age",Arrays.asList(30,31,34,35)).last("limit 1");
//last 无视优化规则直接拼接到sql最后
select中字段不全出现的处理方法
10、名字中包含雨并且年龄小于40(需求1加强版)
第一种情况: select id, name from user where name like '%雨%' and age<40
第二种情况:select id, name, age, email from user where name like '%雨%' and age<40
//第一种情况
queryWrapper.select("id","name").like("name","雨").lt("age",40);
queryWrapper.like("name","雨").lt("age",40).select("id","name");
//第二种情况
queryWrapper.like("name","雨").lt("age",40).select(User.class, info->!info.getColumn().equals("create_time")&&!info.getColumn().equals("manager_id"));
条件构造器中condition作用
condition是执行条件,表示该条件是否加入最后生成的SQL语句中,为true则添加
//条件查询 判断名字或者邮箱是否为空,不为空则添加sql去查询
queryWrapper.like(StringUtils.isNotEmpty(name), "name", name)
.like(StringUtils.isNotEmpty(email, "email", email));
创造条件构造器时传入实体对象
默认实体对象不为空的属性将作为查询条件,默认使用等值条件符
User whereUser = new User();
whereUser.setName("刘强");
whereUser.setAge(32);
QueryWrapper<User> queryWrapper = new QueryWrapper<User>(whereUser);
条件构造器中allEq用法
allEq(Map<R, V> params)
params: key 为数据库字段, value 为字段值
//where id = 1 and name = '老王' and age is null
allEq({id:1, name:"老王", age: null})
allEq(Map<R,V> params, boolean null2IsNull)
null2IsNull: 为true则在map中的value为null时调用isNull方法,为false时则忽略value为null的
//where id = 1 and name = '老王'
allEq({id:1, name:"老王", age: null}, false)
其他条件构造器
11、按照直属上级分组,查询每组的平均年龄、最大年龄、最小年龄。并且只取年龄总和小于500的组
//select avg(age) avg_age, min(age) min_age, max(age) max_age
// from user group by manager_id having sum(age) < 500
queryWrapper.select("avg(age) avg_age","min(age) min_age", "max(age) max_age")
.groupBy("manager_id").having("sum(age)<{0}", 500);
userMapper.selectMaps(queryWrappr);
Lambda条件构造器
三种方式创建lambda构造器
1、new QueryWrapper<User>().lambda();
2、new LambdaQueryWrapper<User>();
3、Wrappers.<User>lambdaQuery();
//where name like '%雨%' and age < 40
lambdaQuery.like(User::getName, "雨").lt(User::getAge,40);
好处在于防误写
new LambdaQueryChainWrapper<User>(userMapper).like(User::getName, "雨")
.ge(User::getAge, 20).list();
使用条件构造器的自定义SQL
更新方法
1、通过ID
2、通过条件构造器
//set age = 30 where name = '李' and age = 29
updateWrapper.eq("name","李").eq("age", 29).set("age", 30);
删除方法