mybatis_plus入门笔记
用到的数据库信息
#创建用户表
CREATE TABLE user (
id BIGINT(20) PRIMARY KEY NOT NULL COMMENT '主键',
name VARCHAR(30) DEFAULT NULL COMMENT '姓名',
age INT(11) DEFAULT NULL COMMENT '年龄',
email VARCHAR(50) DEFAULT NULL COMMENT '邮箱',
manager_id BIGINT(20) DEFAULT NULL COMMENT '直属上级id',
create_time DATETIME DEFAULT NULL COMMENT '创建时间',
CONSTRAINT manager_fk FOREIGN KEY (manager_id)
REFERENCES user (id)
) ENGINE=INNODB CHARSET=UTF8;
#初始化数据:
INSERT INTO user (id, name, age, email, manager_id
, create_time)
VALUES (1087982257332887553, '大boss', 40, 'boss@baomidou.com', NULL
, '2019-01-11 14:20:20'),
(1088248166370832385, '王天风', 25, 'wtf@baomidou.com', 1087982257332887553
, '2019-02-05 11:12:22'),
(1088250446457389058, '李艺伟', 28, 'lyw@baomidou.com', 1088248166370832385
, '2019-02-14 08:31:16'),
(1094590409767661570, '张雨琪', 31, 'zjq@baomidou.com', 1088248166370832385
, '2019-01-14 09:15:15'),
(1094592041087729666, '刘红雨', 32, 'lhm@baomidou.com', 1088248166370832385
, '2019-01-14 09:48:16');
依赖
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>starter-latest-version</version>
</dependency>
springboot配置文件
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
username: root
password: root
url: jdbc:mysql://localhost:3306/test?serverTimezone=CTT&useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true
logging:
level:
root: warn
org.ywb.demo.dao: trace
pattern:
console: '%p%m%n'
配置MapperScan注解
@SpringBootApplication
@MapperScan("com.baomidou.mybatisplus.samples.quickstart.mapper")
public class Application {
public static void main(String[] args) {
SpringApplication.run(QuickStartApplication.class, args);
}
}
常用注解
- @TableName:对数据表名注解
- @TableId:表主键标识
- @TableId(value = “id”, type = IdType.AUTO):自增;
- @TableField:表字段标识
- @TableLogic:表字段逻辑处理注解(逻辑删除)
- @TableField(condition = SqlCondition.LIKE):表示该属性可以模糊搜索。
@Data
@TableName("t_user")
public class User {
@TableId("user_id")
private Long id;
@TableField("real_name")
private String name;
private Integer age;
private String email;
private Long managerId;
private LocalDateTime createTime;
}
CRUD
1.创建实体类
@Data
public class User {
private Long id;
private String name;
private Integer age;
private String email;
private String managerId;
private LocalDateTime createTime;
}
2.在dao包中创建mapper接口,并继承BaseMapper
@Repository
@Mapper
public interface UserDao extends BaseMapper<User> {
List<User> selectAll(@Param(Constants.WRAPPER) Wrapper<User> wrapper);
IPage<User> selectUserPage(Page<User> page, @Param(Constants.WRAPPER) Wrapper<User> wrapper);
}
3.普通查询
@Test
public void selectByMap() {
Map<String, Object> map = new HashMap<>();
map.put("name", "王天风");
map.put("manager_id", 1087982257332887553L);
//where name = 王天风 and manager_id = 1087982257332887553
List<User> users = userMapper.selectByMap(map);
users.forEach(System.out::println);
}
4.条件构造器查询
1.模糊查询
/**
* 查询名字中包含'雨'并且年龄小于40
* where name like '%雨%' and age < 40
*/
@Test
public void selectByWrapper(){
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.like("name","雨").lt("age",40);
List<User> userList = userMapper.selectList(queryWrapper);
userList.forEach(System.out::println);
}
2.嵌套查询
/**
* 创建日期为2019年2月14日并且直属上级姓名为王姓
* date_format(create_time,'%Y-%m-%d') and manager_id in (select id from user where name like '王%')
*/
@Test
public void selectByWrapper2(){
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.apply("date_format(create_time,'%Y-%m-%d')={0}","2019-02-14")
.inSql("manager_id","select id from user where name like '王%'");
List<User> userList = userMapper.selectList(queryWrapper);
userList.forEach(System.out::println);
}
注:日期使用占位符形式进行查询,防止SQL注入
3.and&or
/**
* 名字为王姓,(年龄小于40或者邮箱不为空)
*/
@Test
public void selectByWrapper3(){
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.likeRight("name","王").and(wq-> wq.lt("age",40).or().isNotNull("email"));
List<User> userList = userMapper.selectList(queryWrapper);
userList.forEach(System.out::println);
}
4.between & and
/**
* 名字为王姓,(年龄小于40,并且年龄大于20,并且邮箱不为空)
*/
@Test
public void selectWrapper4(){
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.likeRight("name", "王").and(wq -> wq.between("age", 20, 40).and(wqq -> wqq.isNotNull("email")));
List<User> userList = userMapper.selectList(queryWrapper);
userList.forEach(System.out::println);
}
5.nested
/**
* (年龄小于40或者邮箱不为空)并且名字为王姓
* (age<40 or email is not null)and name like '王%'
*/
@Test
public void selectWrapper5(){
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.nested(wq->wq.lt("age",40).or().isNotNull("email")).likeRight("name","王");
List<User> userList = userMapper.selectList(queryWrapper);
userList.forEach(System.out::println);
}
6.in
/**
* 年龄为30,31,35,34的员工
*/
@Test
public void selectWrapper6(){
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.in("age", Arrays.asList(30,31,34,35));
List<User> userList = userMapper.selectList(queryWrapper);
userList.forEach(System.out::println);
}
condition的作用
@Test
public void testCondition() {
String name = "大";
String email = "";
condition(name, email);
}
public void condition(String name, String email) {
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
/*if (StringUtils.isNotEmpty(name)) {
queryWrapper.like("name", name);
}
if (StringUtils.isNotEmpty(email)) {
queryWrapper.like("email", email);
}*/
queryWrapper.like(StringUtils.isNotEmpty(name),"name", name)
.like(StringUtils.isNotEmpty(email), "email", email);
List<User> users = userMapper.selectList(queryWrapper);
users.forEach(System.out::println);
}
这个condition的作用是为true时,执行其中的SQL条件,为false时,忽略设置的SQL条件。
实体作为条件构造方法的参数
@Test
public void selectByWrapperEntity() {
//WHERE name='王天风' AND age=30 AND name LIKE '%王%' AND age < 40
User whereUser = new User();
whereUser.setName("王天风");
whereUser.setAge(30);
QueryWrapper<User> queryWrapper = new QueryWrapper<>(whereUser);
queryWrapper.like("name", "王").lt("age", 40);
List<User> users = userMapper.selectList(queryWrapper);
users.forEach(System.out::println);
}
Lambda条件构造器
@Test
public void selectLambda() {
//优点:防止属性写错
//WHERE name LIKE ? AND age < ?
LambdaQueryWrapper<User> lambda = new QueryWrapper<User>().lambda();
//LambdaQueryWrapper<User> lambda2 = new LambdaQueryWrapper<>();
//LambdaQueryWrapper<User> lambda3 = Wrappers.<User>lambdaQuery();
lambda.like(User::getName, "王").lt(User::getAge, 40);
List<User> users = userMapper.selectList(lambda);
users.forEach(System.out::println);
}
@Test
public void selectLambda2() {
//WHERE name LIKE ? AND age >= ?
List<User> users = new LambdaQueryChainWrapper<User>(userMapper)
.like(User::getName, "王").ge(User::getAge, 30).list();
users.forEach(System.out::println);
}
自定义SQL
- 在resources资源文件夹下新建mapper文件夹,并将mapper文件夹的路径配置到配置文件中
- 在mapper 文件夹中新建UserMapper.xml。
- 像mybatis那样在UseMapper接口中写接口,在UserMapper接口中写SQL即可。
UserMapper
@Mapper
@Repository
public interface UserMapper extends BaseMapper<User> {
@Select("select * from user ${ew.customSqlSegment}")
List<User> selectAll(@Param(Constants.WRAPPER) Wrapper<User> wrapper);
}
UserMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.ywb.demo.dao.UserMapper">
<select id="selectAll" resultType="org.ywb.demo.pojo.User">
select * from user
</select>
</mapper>
分页查询
- 新建config类,在config类中创建 PaginationInterceptor 对象
@Configuration
public class MybatisPlusConfig {
@Bean
public PaginationInterceptor paginationInterceptor(){
return new PaginationInterceptor();
}
}
- 测试
/**
* 查询年龄大于20 的用户信息,并以每页容量为两条分页的形式返回。
*/
@Test
public void selectPage(){
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.ge("age",20);
//设置当前页和页容量
Page<User> page = new Page<>(1, 2);
IPage<User> userIPage = userMapper.selectPage(page, queryWrapper);
System.out.println("总页数:"+userIPage.getPages());
System.out.println("总记录数:"+userIPage.getTotal());
userIPage.getRecords().forEach(System.out::println);
}
更新
@Test
public void updateById() {
//UPDATE user SET age=?, email=? WHERE id=?
User user = new User();
user.setId(1087982257332887553L);
user.setAge(41);
user.setEmail("daboss@baomidou.com");
int rows = userMapper.updateById(user);
System.out.println("影响记录数:" + rows);
}
@Test
public void updateByWrapper() {
//UPDATE user SET email=? WHERE name = ? AND age = ?
UpdateWrapper<User> userUpdateWrapper = new UpdateWrapper<>();
userUpdateWrapper.eq("name", "王天风").eq("age", 41);
User user = new User();
user.setEmail("boss@qq.com");
int update = userMapper.update(user, userUpdateWrapper);
System.out.println("影响记录数:" + update);
}
@Test
public void updateByWrapper1() {
//UPDATE user SET email=? WHERE name LIKE CONCAT('%',?,'%')
//like是因为在实体类name属性上使用了注解@TableField(condition = SqlCondition.LIKE)
User whereUser = new User();
whereUser.setName("王天风");
UpdateWrapper<User> userUpdateWrapper = new UpdateWrapper<>(whereUser);
User user = new User();
user.setEmail("boss@qq.com");
int update = userMapper.update(user, userUpdateWrapper);
System.out.println("影响记录数:" + update);
}
@Test
public void updateByWrapper2() {
UpdateWrapper<User> userUpdateWrapper = new UpdateWrapper<>();
//不使用实体类更新用户
userUpdateWrapper.eq("name", "王天风").eq("age", 41).set("age", 42);
int update = userMapper.update(null, userUpdateWrapper);
System.out.println("影响记录数:" + update);
}
@Test
public void updateByWrapperLambda() {
LambdaUpdateWrapper<User> userLambdaUpdateWrapper = Wrappers.<User>lambdaUpdate();
userLambdaUpdateWrapper.eq(User::getName, "王天风").eq(User::getAge, 42).set(User::getAge, 41);
int update = userMapper.update(null, userLambdaUpdateWrapper);
System.out.println("影响记录数:" + update);
}
@Test
public void updateByWrapperLambdaChain() {
boolean flag = new LambdaUpdateChainWrapper<>(userMapper)
.eq(User::getName, "王天风").eq(User::getAge, 41).set(User::getAge, 42).update();
System.out.println("更新:"+flag);
}
删除
@Test
public void deleteById() {
int rows = userMapper.deleteById(1178106259337924609L);
System.out.println("删除条数:" + rows);
}
@Test
public void deleteByMap() {
//DELETE FROM user WHERE name = ? AND age = ?
Map<String, Object> paramsMap = new HashMap<>();
paramsMap.put("name", "salesman");
paramsMap.put("age", 31);
int i = userMapper.deleteByMap(paramsMap);
System.out.println("删除条数:" + i);
}
@Test
public void deleteBatchIds() {
int i = userMapper.deleteBatchIds(Arrays.asList(58L, 66L));
System.out.println("删除条数:" + i);
}
@Test
public void deleteByWrapper() {
//DELETE FROM user WHERE age = ? OR age > ?
LambdaQueryWrapper<User> lambdaQueryWrapper = Wrappers.<User>lambdaQuery();
lambdaQueryWrapper.eq(User::getAge, 27).or().gt(User::getAge, 50);
int delete = userMapper.delete(lambdaQueryWrapper);
System.out.println("删除条数:" + delete);
}
AR模式
AR模式:简单来说, 就是通过实体类对象直接对表的增删改查操作
实体类继承Model类
@Data
@EqualsAndHashCode(callSuper = false)//继承Model的时候使用
@TableName("user")
public class User extends Model<User> {//AR
private static final long serialVersionUID = 1L;//继承Model的时候使用
@Test
public void insert() {
User user = new User();
user.setName("engineer");
user.setAge(33);
user.setEmail("123@qq.com");
user.setManagerId(1088248166370832385L);
user.setCreateTime(LocalDateTime.now());
boolean insertFlag = user.insert();
System.out.println(insertFlag);
}
@Test
public void selectById() {
User user = new User();
User userSelect = user.selectById(1088248166370832385L);
System.out.println(userSelect == user);//false
System.out.println(userSelect);
}
主键策略
MyBatisPlus的主键策略封装在IdType枚举类中。
@Getter
public enum IdType {
/**
* 数据库ID自增
*/
AUTO(0),
/**
* 该类型为未设置主键类型,未设置默认雪花算法
*/
NONE(1),
/**
* 用户输入ID
* <p>该类型可以通过自己注册自动填充插件进行填充</p>
*/
INPUT(2),
/* 以下3种类型、只有当插入对象ID 为空,才自动填充。雪花算法 */
/**
* 全局唯一ID (idWorker)
*/
ID_WORKER(3),
/**
* 全局唯一ID (UUID)
*/
UUID(4),
/**
* 字符串全局唯一ID (idWorker 的字符串表示)
*/
ID_WORKER_STR(5);
private final int key;
IdType(int key) {
this.key = key;
}
}
在实体类中对应数据库中的主键id属性上标注注解TableId(type=‘xxx’)即可完成主键配置。
@TableId(type = IdType.AUTO)
private Long id;
全局主键策略实现
在application.yml增加全局主键策略配置
mybatis-plus:
#全局主键策略配置
global-config:
db-config:
id-type: uuid
如果全局策略和局部策略全都设置,局部策略优先。
通用 service
public interface UserService extends IService<User> {
}
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
}
@Autowired
private UserService userService;
@Test
public void getOne() {
//返回结果多个会报错
//User one = userService.getOne(Wrappers.<User>lambdaQuery().gt(User::getAge, 25));
//返回结果多个不会报错,只取第一个
User one = userService.getOne(Wrappers.<User>lambdaQuery().gt(User::getAge, 25), false);
System.out.println(one);
}
@Test
public void Batch() {
User user1 = new User();
user1.setName("engineer3");
user1.setAge(24);
User user2 = new User();
user2.setName("engineer4");
user2.setAge(26);
List<User> userList = Arrays.asList(user1, user2);
boolean saveFlag = userService.saveBatch(userList);
System.out.println(saveFlag);
}
@Test
public void chain() {
List<User> userList = userService.lambdaQuery().gt(User::getAge, 25).like(User::getName, "pro").list();
userList.forEach(System.out::println);
}
@Test
public void chain1() {
boolean update = userService.lambdaUpdate().eq(User::getAge, 25).set(User::getAge, 26).update();
System.out.println(update);
}
@Test
public void chain2() {
boolean remove = userService.lambdaUpdate().eq(User::getAge, 24).remove();
System.out.println(remove);
}