MyBatis-Plus - 快速入门

1、数据库建表

# 创建用户表
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, '[email protected]', NULL
        , '2019-01-11 14:20:20'),
    (1088248166370832385, '王天风', 25, '[email protected]', 1087982257332887553
        , '2019-02-05 11:12:22'),
    (1088250446457389058, '李艺伟', 28, '[email protected]', 1088248166370832385
        , '2019-02-14 08:31:16'),
    (1094590409767661570, '张雨琪', 31, '[email protected]', 1088248166370832385
        , '2019-01-14 09:15:15'),
    (1094592041087729666, '刘红雨', 32, '[email protected]', 1088248166370832385
        , '2019-01-14 09:48:16');

2、依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <scope>runtime</scope>
</dependency>

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-configuration-processor</artifactId>
    <optional>true</optional>
</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>

<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>3.1.2</version>
</dependency>

3、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'

4、创建相关包,如图

5、在pojo包中新建和数据库user表映射的类

@Data
public class User {
    private Long id;
    private String name;
    private Integer age;
    private String email;
    private String managerId;
    private LocalDateTime createTime;
}

6、在dao包中创建mapper接口,并集成mybatisPlus的BaseMapper

public interface UserMapper extends BaseMapper<User> {

}

7、在springboot启动类添加@MapperScan扫描dao层接口

@MapperScan("org.ywb.demo.dao")
@SpringBootApplication
public class MybatisPlusDemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(MybatisPlusDemoApplication.class, args);
    }

}

8、编写测试类

@RunWith(SpringRunner.class)
@SpringBootTest
public class MybatisPlusDemoApplicationTests {

    @Resource
    private UserMapper userMapper;
    
    @Test
    public void select(){
        List<User> users = userMapper.selectList(null);
        users.forEach(System.out::println);
    }

}

9、运行结果

新增方法

UserMapper代码

package com.neo.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.neo.model.User;
import org.apache.ibatis.annotations.Mapper;

//要使用mp,就要集成BaseMapper
@Mapper
public interface UserMapper extends BaseMapper<User> {

}

在测试方法中调用userMapper中的insert方法

@Test
public void insert(){
    User user = new User();
    user.setName("黄小明");
    user.setAge(20);
    user.setManagerId(1088248166370832385L);
    user.setCreateTime(LocalDateTime.now());
    int rows = userMapper.insert(user);
    System.out.println("影响记录数:"+rows);

}

测试结果

DEBUG==> Preparing: INSERT INTO user ( id, name, age, manager_id, create_time ) VALUES ( ?, ?, ?, ?, ? ) DEBUG==> Parameters: 1223961279246393345(Long), 黄小明(String), 20(Integer), 1088248166370832385(Long), 2020-02-02T21:28:03.621(LocalDateTime) DEBUG<== Updates: 1 影响记录数:1

 

常用注解

MyBatisPlus提供了一些注解供我们在实体类和表信息出现不对应的时候使用。通过使用注解完成逻辑上匹配。

注解名称 说明
@TableName 实体类的类名和数据库表名不一致
@TableId 实体类的主键名称和表中主键名称不一致
@TableField 实体类中的成员名称和表中字段名称不一致

@TabName注解

当修改数据库表明却不想修改实体类型时,可以通过@TabName("数据库表名")来指定表名,否则会运行报错。

@Data
@TableName("mp_user")
public class User {
    //主键
    private Long id;
    //姓名
    private String name;
    //年龄
    private Integer age;
    //邮箱
    private String email;
    //直属上级
    private Long managerId;
    //创建时间
    private LocalDateTime createTime;
}

@TabId注解

当实例中主键与数据库中的主键名称不一致时(例如实例中为驼峰命名,数据库表中为下划线命名),可使用该注解。

@TableField注解

当实例中的字段与数据库中的字段不同时,就可以使用该注解映射,如下例

@TableField("name")
private String realName;

排除非表字段的三种方式

第一:在声明类属性时使用 transient 关键字声明。

第二:如上方法可能无法序列化该字段,故可以在声明类属性时:使用 static 关键字声明为静态变量(注意,用static 声明的静态变量lombok不会为其添加set和get方法)。

第三:使用@TableField(exist = false)注解注解 其中括号中的 exist = false 表示该字段不是数据库表中的字段,无需映射。

基本查询方法

通过id查询:selectById()方法

@Test
public void selectById() {
    User user = userMapper.selectById(1094590409767661570L);
    System.out.println(user);
}

批量查询:selectBatchIds()

@Test
public void selectByIds() {
    List<Long> idsList = Arrays.asList(1094592041087729666L, 1223961279246393345L, 1088250446457389058L);
    List<User> users = userMapper.selectBatchIds(idsList);
    users.forEach(System.out::println);
}

通过map查询

@Test
public void selectByMap() {
    Map<String,Object> columnMap = new HashMap<>();
    columnMap.put("name","王天风");
    columnMap.put("age",25);
    //通过此map会执行类似 where name="王天风" and age=25 的sql
    List<User> userList = userMapper.selectByMap(columnMap);
    userList.forEach(System.out::println);
}

注意:此map中的键名为数据表中列名,并非实体类中的属性名

以条件构造器为参数的查询方法

/* 
	查询要求:
	1、名字中包含雨并且年龄小于40
	name like '%雨%' and age<40
 */
@Test
public void selectByWrapper() {
    QueryWrapper<User> queryWrapper = new QueryWrapper<>();
    //等同于
    //QueryWrapper<User> query = Wrappers.<User>query();
    queryWrapper.like("name","雨").lt("age",40);
    //注意:此处的键名依旧为数据库中的列名
    List<User> userList = userMapper.selectList(queryWrapper);
    userList.forEach(System.out::println);
}


/*
	2、名字中包含雨年并且龄大于等于20且小于等于40并且email不为空
	name like '%雨%' and age between 20 and 40 and email is not null
 */
@Test
public void selectByWrapper2() {
    QueryWrapper<User> queryWrapper = new QueryWrapper<>();
    //等同于
    //QueryWrapper<User> query = Wrappers.<User>query();
    queryWrapper.like("name","雨").between("age",20,40).isNotNull("email");
    //注意:此处的键名依旧为数据库中的列名
    List<User> userList = userMapper.selectList(queryWrapper);
    userList.forEach(System.out::println);
}


/*
	3、名字为王姓或者年龄大于等于25,按照年龄降序排列,年龄相同按照id升序排列
	name like '王%' or age>=25 order by age desc,id asc
 */
@Test
public void selectByWrapper3() {
    QueryWrapper<User> queryWrapper = new QueryWrapper<>();
    //等同于
    //QueryWrapper<User> query = Wrappers.<User>query();
    queryWrapper.likeRight("name","王").or()
            .ge("age",25).orderByDesc("age").orderByAsc("id");

    //注意:此处的键名依旧为数据库中的列名
    List<User> userList = userMapper.selectList(queryWrapper);
    userList.forEach(System.out::println);
}


/*
	4、创建日期为2019年2月14日并且直属上级为名字为王姓
	date_format(create_time,'%Y-%m-%d')='2019-02-14' and manager_id in (select id from user where name like '王%')
 */
@Test
public void selectByWrapper4() {
    QueryWrapper<User> queryWrapper = new QueryWrapper<>();
    //等同于
    //QueryWrapper<User> query = Wrappers.<User>query();
    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注入风险
//queryWrapper.apply("date_format(create_time,'%Y-%m-%d')="2019-02-14")


/*
	5、名字为王姓并且(年龄小于40或邮箱不为空)
	name like '王%' and (age<40 or email is not null)
 */
@Test
public void selectByWrapper5() {
    QueryWrapper<User> queryWrapper = new QueryWrapper<>();
    //等同于
    //QueryWrapper<User> query = Wrappers.<User>query();
    queryWrapper.likeRight("name","王").
            and(wq->wq.lt("age",40)
            .or().isNotNull("email"));
    //注意:此处的键名依旧为数据库中的列名
    List<User> userList = userMapper.selectList(queryWrapper);
    userList.forEach(System.out::println);
}


/*
	6、名字为王姓或者(年龄小于40并且年龄大于20并且邮箱不为空)
	name like '王%' or (age<40 and age>20 and email is not null)
 */
@Test
public void selectByWrapper6() {
    QueryWrapper<User> queryWrapper = new QueryWrapper<>();
    //等同于
    //QueryWrapper<User> query = Wrappers.<User>query();
    queryWrapper.likeRight("name","王")
            .or(wq->wq.lt("age",40).gt("age",20).isNotNull("email"));

    //注意:此处的键名依旧为数据库中的列名
    List<User> userList = userMapper.selectList(queryWrapper);
    userList.forEach(System.out::println);
}


/*
	7、(年龄小于40或邮箱不为空)并且名字为王姓
	(age<40 or email is not null) and name like '王%'
 */
@Test
public void selectByWrapper7() {
    QueryWrapper<User> queryWrapper = new QueryWrapper<>();
    //等同于
    //QueryWrapper<User> query = Wrappers.<User>query();
    queryWrapper.nested(wq->wq.lt("age",40).or().
            isNotNull("email"))
            .likeRight("name","王");
    //注意:此处的键名依旧为数据库中的列名
    List<User> userList = userMapper.selectList(queryWrapper);
    userList.forEach(System.out::println);
}


/*
	8、年龄为30、31、34、35
	age in (30、31、34、35)
 */
@Test
public void selectByWrapper8() {
    QueryWrapper<User> queryWrapper = new QueryWrapper<>();
    //等同于
    //QueryWrapper<User> query = Wrappers.<User>query();
  	queryWrapper.in("age",Arrays.asList(30,31,34,35));
    //注意:此处的键名依旧为数据库中的列名
    List<User> userList = userMapper.selectList(queryWrapper);
    userList.forEach(System.out::println);
}
/**
 * 无视优化规则直接拼接到 sql 的最后(有sql注入的风险,请谨慎使用)
 * <p>例: last("limit 1")</p>
 * <p>注意只能调用一次,多次调用以最后一次为准</p>
 *
 * @param condition 执行条件
 * @param lastSql   sql语句
 * @return children
 */
Children last(boolean condition, String lastSql);


/**
 * 9. 只返回满足条件的一条语句即可
 *    limit 1
 */
@Test
public void selectWrapper7(){
    QueryWrapper<User> queryWrapper = new QueryWrapper<>();

    queryWrapper.in("age", Arrays.asList(30,31,34,35)).last("limit 1");

    List<User> userList = userMapper.selectList(queryWrapper);
    userList.forEach(System.out::println);
}

  • last 有SQL注入的风险!!!

select中字段不全出现的处理方法

并非每次查询都要查询所有字段,测试可用如下方法查询

/*
	10、名字中包含雨并且年龄小于40(需求1加强版)
	第一种情况
	select id,name
	from user
	where name like '%雨%' and age<40
*/
@Test
public void selectByWrapperSuper() {
	QueryWrapper<User> queryWrapper = new QueryWrapper<>();
	queryWrapper.select("id","name").like("name","雨").lt("age",40);
	List<User> userList =userMapper.selectList(queryWrapper);
	userList.forEach(System.out::println);
}


/*
	第二种情况
	select id,name,age,email
	from user
	where name like '%雨%' and age<40
*/
@Test
public void selectByWrapperSuper2() {
    QueryWrapper<User> queryWrapper = new QueryWrapper<>();
    queryWrapper.like("name","雨").lt("age",40)
    .select(User.class,info->!info.getColumn().equals("create_time")
            &&!info.getColumn().equals("manager_id"));
    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> userList =userMapper.selectList(queryWrapper);
    userList.forEach(System.out::println);
}

 

创建条件构造器时传入实体对象

如果想通过对象中某些属性进行模糊查询,我们可以在跟数据库表对应的实体类中相应的属性标注注解即可。
比如我们想通过姓名进行模糊查询用户列表。

@TableField(condition = SqlCondition.LIKE)
private String name;
@Test
public void selectWrapper10(){
    User user = new User();
    user.setName("红");
    user.setAge(32);
    QueryWrapper<User> queryWrapper = new QueryWrapper<>(user);
    List<User> userList = userMapper.selectList(queryWrapper);
    userList.forEach(System.out::println);
}

  • 当然可以通过源码对照 SqlCondition 对应的作用

  • 如果源码中没有找到想要的功能,还可以自定义,如图

条件构造器中allEq用法

/**
 * allEq
 */
@Test
public void selectList_allEq() {
    QueryWrapper<User> query = new QueryWrapper<>();
    Map<String, Object> params = new HashMap<>();
    params.put("name", "刘明强");
    params.put("age", 31);
    params.put("email", null);
//        query.allEq(params,false);//第二个参数表示如果列值为null是否按IS NULL查询,false则忽略null列的查询
    query.allEq((k, v) -> !k.equals("name"), params, false);//第一个参数是过滤器
    List<User> list = userMapper.selectList(query);
    list.forEach(System.out::println);
}

其他以条件构造器为参数的查询方法

/**
 * selectMaps的应用场景1:当表中的列特别多,但实际只需要几个列时,这时返回一个实体类有些不必要
 */
@Test
public void selectMaps() {
    QueryWrapper<User> query = new QueryWrapper<>();
    query.like("name", "雨").lt("age", 40).select("name", "age");
    List<Map<String, Object>> maps = userMapper.selectMaps(query);
    maps.forEach(System.out::println);
}


/**
 * selectMaps的应用场景2:查询统计结果
 * 按照直属上级分组,查询每组的平均年龄、最大年龄、最小年龄,并且只取年龄总和小于100的组
 * SELECT AVG(age) avg_age,MIN(age) min_age,MAX(age) max_age
 * FROM `user`
 * GROUP BY `manager_id`
 * HAVING SUM(age)<100;
 */
@Test
public void selectMaps2() {
    QueryWrapper<User> query = new QueryWrapper<>();
    query.select("AVG(age) avg_age", "MIN(age) min_age", "MAX(age) max_age")
        .groupBy("manager_id")
        .having("SUM(age)<{0}", 100);
    List<Map<String, Object>> maps = userMapper.selectMaps(query);
    maps.forEach(System.out::println);
}


/**
 * selectObjs只返回第一列,其它列被遗弃
 * 应用场景:只需返回一列的时候
 */
@Test
public void selectObjs() {
    QueryWrapper<User> query = new QueryWrapper<>();
    query.like("name", "雨").lt("age", 40).select("name", "age");
    List<Object> list = userMapper.selectObjs(query);
    list.forEach(System.out::println);
}


/**
 * 返回总记录数
 */
@Test
public void selectCount() {
    QueryWrapper<User> query = new QueryWrapper<>();
    query.like("name", "雨").lt("age", 40);
    Integer count = userMapper.selectCount(query);
    System.out.println("总记录数:" + count);
}


/**
 * selectOne:只能查询一条记录,查询到多条会报错
 */
@Test
public void selectOne() {
    QueryWrapper<User> query = new QueryWrapper<>();
    query.like("name", "刘红雨").lt("age", 40);
    User user = userMapper.selectOne(query);
    System.out.println(user);
}

Lambda条件构造器

/**
 * lambda条件构造器
 */
@Test
public void lambdaQueryWrapper1() {
//        LambdaQueryWrapper<User> lambdaQ = new QueryWrapper<User>().lambda();
//        LambdaQueryWrapper<User> lambdaQ = new LambdaQueryWrapper<>();
    LambdaQueryWrapper<User> lambdaQ = Wrappers.<User>lambdaQuery();

    lambdaQ.like(User::getName, "雨").lt(User::getAge, 40);
    List<User> list = userMapper.selectList(lambdaQ);
    list.forEach(System.out::println);
}

/**
 * lambda条件构造器:防误写(例如列名"name"可能被误写)
 */
@Test
public void lambdaQueryWrapper2() {
    LambdaQueryWrapper<User> query = new LambdaQueryWrapper<>();
    query.likeRight(User::getName, "王")
        .and(q -> q.lt(User::getAge, 40).or().isNotNull(User::getEmail));
    List<User> list = userMapper.selectList(query);
    list.forEach(System.out::println);
}

/**
 * 链式lambda条件构造器:更优雅的书写方式
 */
@Test
public void lambdaQueryChainWrapper() {
    List<User> list = new LambdaQueryChainWrapper<User>(userMapper)
        .likeRight(User::getName, "王")
        .and(
            q -> q
                .lt(User::getAge, 40)
                .or()
                .isNotNull(User::getEmail)
        )
        .list();
    list.forEach(System.out::println);
}

使用条件构造器的自定义SQL

(要求版本大于等于3.0.7)

在UserMapper中定于接口方法(采用注解的方式)

@Select("select * from user ${ew.customSqlSegment}")
List<User> selectAll(@Param(Constants.WRAPPER)Wrapper<User> wrapper);

在测试中使用自定义方法

@Test
public void selectMy() {
//        LambdaQueryWrapper<User> lambda = new QueryWrapper<User>().lambda();
//        LambdaQueryWrapper<User> userLambdaQueryWrapper = new LambdaQueryWrapper<>();
    LambdaQueryWrapper<User> lambdaQuery = Wrappers.<User>lambdaQuery();

    lambdaQuery.like(User::getName,"雨").lt(User::getAge,40);
    //where name like '%雨%'
    List<User> userList = userMapper.selectAll(lambdaQuery);//此处使用自定义接口方法
    userList.forEach(System.out::println);

}

如果不想把自定义sql写在接口中,例如写在xml中,还可以采用如下方法:

第一步:在yml配置文件中配置接口对应的xml路径

Mybatis-plus:
  mapper-locations: classpath:mp/mapper/*.xml

在配置路径下新建UserMapper.xml文件,同时去除接口中的注解sql

<?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="com.neo.mapper.UserMapper" >
    <select id="selectAll" resultType="com.neo.model.User">
        select * from user ${ew.customSqlSegment}
    </select>
</mapper>

mybatis中提供分页方法,但是该分页是逻辑分页,而非物理分页。

MP分页插件实现物理分页

新建配置包(com.neo.configuration)并新建配置分页类MybatisPlusConfig:

@Configuration
public class MybatisPlusConfig {
    @Bean
    public PaginationInterceptor paginationInterceptor() {
        return new PaginationInterceptor();
    }
}

测试(selectPage)

@Test
public void selectPage() {
    QueryWrapper<User> queryWrapper = new QueryWrapper<User>();
    queryWrapper.ge("age", 26);
    Page<User> page = new Page<>(1, 2);
    IPage<User> iPage = userMapper.selectPage(page, queryWrapper);
    System.out.println("总页数:" + iPage.getPages());
    System.out.println("总记录数:" + iPage.getTotal());
    List<User> userlist = iPage.getRecords();
    userlist.forEach(System.out::println);
}

运行日志:

DEBUG==>  Preparing: SELECT COUNT(1) FROM user WHERE age >= ? 
DEBUG==> Parameters: 26(Integer)
TRACE<==    Columns: COUNT(1)
TRACE<==        Row: 7
DEBUG==>  Preparing: SELECT id,name,age,email,manager_id,create_time FROM user WHERE age >= ? LIMIT ?,? 
DEBUG==> Parameters: 26(Integer), 0(Long), 2(Long)
TRACE<==    Columns: id, name, age, email, manager_id, create_time
TRACE<==        Row: 1087982257332887553, 大boss, 40, [email protected], null, 2019-01-11 14:20:20
TRACE<==        Row: 1088250446457389058, 李艺伟, 28, [email protected], 1088248166370832385, 2019-02-14 08:31:16
DEBUG<==      Total: 2
总页数:4
总记录数:7
User(id=1087982257332887553, name=大boss, age=40, [email protected], managerId=null, createTime=2019-01-11T14:20:20)
User(id=1088250446457389058, name=李艺伟, age=28, [email protected], managerId=1088248166370832385, createTime=2019-02-14T08:31:16)

测试(selectMapsPage)

@Test
public void selectPage() {
    QueryWrapper<User> queryWrapper = new QueryWrapper<User>();
//        queryWrapper.ge("age",26);
    Page<User> page = new Page<>(1, 2);
//        IPage<User> iPage = userMapper.selectPage(page, queryWrapper);
//        System.out.println("总页数:"+ iPage.getPages());
//        System.out.println("总记录数:"+ iPage.getTotal());
//        List<User> userlist = iPage.getRecords();
    IPage<Map<String, Object>> iPage = userMapper.selectMapsPage(page, queryWrapper);
    System.out.println("总页数:"+ iPage.getPages());
    System.out.println("总记录数:"+ iPage.getTotal());
    List<Map<String, Object>> userlist = iPage.getRecords();
    userlist.forEach(System.out::println);
}

DEBUG==>  Preparing: SELECT COUNT(1) FROM user 
DEBUG==> Parameters: 
TRACE<==    Columns: COUNT(1)
TRACE<==        Row: 13
DEBUG==>  Preparing: SELECT id,name,age,email,manager_id,create_time FROM user LIMIT ?,? 
DEBUG==> Parameters: 0(Long), 2(Long)
TRACE<==    Columns: id, name, age, email, manager_id, create_time
TRACE<==        Row: 1087982257332887553, 大boss, 40, [email protected], null, 2019-01-11 14:20:20
TRACE<==        Row: 1088248166370832385, 王天风, 25, [email protected], 1087982257332887553, 2019-02-05 11:12:22
DEBUG<==      Total: 2
总页数:7
总记录数:13
{createTime=2019-01-11 14:20:20.0, name=大boss, id=1087982257332887553, age=40, [email protected]}
{createTime=2019-02-05 11:12:22.0, name=王天风, id=1088248166370832385, managerId=1087982257332887553, age=25, [email protected]}

从以上两个例子看以看出每个是执行了两条sql语句,如果只想要查询结果,不想要查询总数,只需要将page的第三个参数变为false,即可:

Page<User> page = new Page<>(1, 2,false);
  • 当我们在做多表联查时,就不能使用如上方式查询了,此时可以在xml文件中自定义sql。

根据id更新

@Test
public void updateById(){
    User user= new User();
    user.setId(1088248166370832385L);
    user.setAge(26);
    user.setEmail("[email protected]");
    int rows = userMapper.updateById(user);
    System.out.println("影响记录数:"+ rows);
}

运行日志:

DEBUG==>  Preparing: UPDATE user SET age=?, email=? WHERE id=? 
DEBUG==> Parameters: 26(Integer), [email protected](String), 1088248166370832385(Long)
DEBUG<==    Updates: 1
影响记录数:1

以条件构造器作为参数的更新方法

@Test
public void updateByWrapper(){
    UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();
    updateWrapper.eq("name","李艺伟").eq("age",28);
    User user = new User();
    user.setEmail("[email protected]");
    user.setAge(29);
    int rows = userMapper.update(user, updateWrapper);
    System.out.println("影响行数:"+rows
    );
}

运行日志:
DEBUG==>  Preparing: UPDATE user SET age=?, email=? WHERE name = ? AND age = ? 
DEBUG==> Parameters: 29(Integer), [email protected](String), 李艺伟(String), 28(Integer)
DEBUG<==    Updates: 1
影响行数:1

条件构造器中set方法使用

(只修改少量字段时)

@Test
public void updateByWrapper(){
    UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();
    //通过条件构造器的链式编程设置更新信息
    updateWrapper.eq("name","李艺伟").eq("age",29).set("email","[email protected]");
	//   User user = new User();

    int rows = userMapper.update(null, updateWrapper);
    System.out.println("影响行数:"+rows);
}

lambda条件构造器更新

@Test
public void updateByWrapperLambda(){
    LambdaUpdateWrapper<User> lambdaUpdate = Wrappers.<User>lambdaUpdate();
    lambdaUpdate.eq(User::getName,"李艺伟").eq(User::getAge,29).set(User::getAge,31);
    int rows = userMapper.update(null, lambdaUpdate);
    System.out.println("影响行数:"+rows);
}

根据id删除的方法

@Test
public void deleteById() {
   int rows= userMapper.deleteById(1223976086888599553L);
   System.out.println("影响行数:"+rows);
}

根据id批量删除

@Test
public void deleteBatchIds() {
    int rows =  userMapper.deleteBatchIds(
            Arrays.asList(1223973741031141377L,
            1223972327026405378L,1223970002606067714L));

    System.out.println("影响行数:"+rows);
}

 

其他普通删除方法

@Test
public void deleteByMap() {
    Map<String,Object> columnMap= new HashMap<>();
    columnMap.put("name","向后");
    columnMap.put("age","31");
    int rows = userMapper.deleteByMap(columnMap);
    System.out.println("影响行数:"+rows);
}

以条件构造器为参数的删除方法

AR模式(Active Record)

直接通过实体类完成对数据的增删改查。

实体类继承Model类

@Data
@EqualsAndHashCode(callSuper = false)
public class User extends Model<User> {
    private Long id;
    @TableField(condition = SqlCondition.LIKE)
    private String name;
    private Integer age;
    private String email;
    private Long managerId;
    private LocalDateTime createTime;
}

Model类中封装了很多增删改查方法,不用使用UserMapper即可完成对数据的增删改查。

查询所有用户信息

@Test
public void test(){
    User user = new User();
    user.selectAll().forEach(System.out::println);
}

 

主键策略

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;

这种配置方式的主键策略只能在该表中生效,但是其他表还需要进行配置,为了避免冗余,麻烦,MybatisPlus提供了全局配置,在配置文件中配置主键策略即可实现。

mybatis-plus:
  mapper-locations: mapper/*.xml
  global-config:
    db-config:
      id-type: auto
  • 如果全局策略和局部策略全都设置,局部策略优先。

基本配置

mybatis-plus:
  mapper-locations: mapper/*.xml
  global-config:
    db-config:
      # 主键策略
      id-type: auto
      # 表名前缀
      table-prefix: t
      # 表名是否使用下划线间隔,默认:是
      table-underline: true
  # 添加mybatis配置文件路径
  config-location: mybatis-config.xml
  # 配置实体类包地址
  type-aliases-package: org.ywb.demo.pojo
  # 驼峰转下划线
  configuration:
    map-underscore-to-camel-case: true
  • config-location & configuration 不能同时出现,否则报错。

通用Service

定义接口继承IService

public interface UserService extends IService<User>{}

定义接口的实现类

@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService{}

猜你喜欢

转载自blog.csdn.net/Dream_Weave/article/details/106543452