MyBatis-Plus基础教程

MyBatis-Plus

只讲解基础部分,深入了解mybatis-plus可前往mybatis-plus 官网

1、简介

1.1、特性

  • 无侵入:只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑

  • 损耗小:启动即会自动注入基本 CURD,性能基本无损耗,直接面向对象操作

  • 强大的 CRUD 操作:内置通用 Mapper、通用 Service,仅仅通过少量配置即可实现单表大部分 CRUD 操作,更有强大的条件构造器,满足各类使用需求

  • 支持 Lambda 形式调用:通过 Lambda 表达式,方便的编写各类查询条件,无需再担心字段写错

  • 支持主键自动生成:支持多达 4 种主键策略(内含分布式唯一 ID 生成器 - Sequence),可自由配置,完美解决主键问题

  • 支持 ActiveRecord 模式:支持 ActiveRecord 形式调用,实体类只需继承 Model 类即可进行强大的 CRUD 操作

  • 支持自定义全局通用操作:支持全局通用方法注入( Write once, use anywhere )

  • 内置代码生成器:采用代码或者 Maven 插件可快速生成 Mapper 、 Model 、 Service 、 Controller 层代码,支持模板引擎,更有超多自定义配置等您来使用

  • 内置分页插件:基于 MyBatis 物理分页,开发者无需关心具体操作,配置好插件之后,写分页等同于普通 List 查询

  • 分页插件支持多种数据库:支持 MySQL、MariaDB、Oracle、DB2、H2、HSQL、SQLite、Postgre、SQLServer 等多种数据库

  • 内置性能分析插件:可输出 SQL 语句以及其执行时间,建议开发测试时启用该功能,能快速揪出慢查询

  • 内置全局拦截插件:提供全表 delete 、 update 操作智能分析阻断,也可自定义拦截规则,预防误操作

1.2、框架结构

framework

2、快速入门

2.1、mybatis实现查询

项目结构

image

maven依赖

<dependencies>
    <!-- https://mvnrepository.com/artifact/com.baomidou/mybatis-plus -->
    <dependency>
        <groupId>com.baomidou</groupId>
        <artifactId>mybatis-plus</artifactId>
        <version>3.3.2</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>8.0.16</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/com.alibaba/druid -->
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>druid</artifactId>
        <version>1.1.22</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>1.18.12</version>
        <scope>provided</scope>
    </dependency>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
        <scope>test</scope>
    </dependency>
</dependencies>

User.java

package com.example.pojo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

/**
 * @author admin
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {

    private int id;
    private String userName;
    private String password;
    private String name;
    private Integer age;
    private String email;
}

UserMapper.java

package com.example.mapper;

import com.example.pojo.User;

import java.util.List;

/**
 * @author admin
 */
public interface UserMapper {

    /**
     * 获取全部用户
     * @return
     */
    List<User> getAllUser();
}

db.properties

jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/test?characterEncoding=utf8&useSSL=true&serverTimezone=UTC
jdbc.username=root
jdbc.password=123456

mybatis-config.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <properties resource="db.properties"/>
    <settings>
        <setting name="logImpl" value="STDOUT_LOGGING"/>
    </settings>
    <typeAliases>
        <package name="com.example.pojo"/>
    </typeAliases>
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="${jdbc.driver}"/>
                <property name="url" value="${jdbc.url}"/>
                <property name="username" value="${jdbc.username}"/>
                <property name="password" value="${jdbc.password}"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <mapper resource="UserMapper.xml"/>
    </mappers>
</configuration>

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="com.example.mapper.UserMapper">
    <select id="getAllUser" resultType="user">
        select * from tb_user
    </select>
</mapper>

测试

package com.example.mapper;

import com.example.pojo.User;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Test;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;

public class UserMapperTest {

    @Test
    public void testGetAllUser() throws IOException {
        InputStream stream = Resources.getResourceAsStream("mybatis-config.xml");
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(stream);
        SqlSession sqlSession = sqlSessionFactory.openSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        List<User> userList = mapper.getAllUser();
        for (User user : userList) {
            System.out.println(user);
        }
        sqlSession.close();
    }
}

结果

image

2.2、mybatis-plus实现查询

User.java

package com.example.pojo;

import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

/**
 * @TableName 指定该实体在数据库中映射的表
 * @author admin
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
@TableName("tb_user")
public class User {

    private int id;
    private String userName;
    private String password;
    private String name;
    private Integer age;
    private String email;
}

UserMapper.java

package com.example.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.example.pojo.User;

import java.util.List;

/**
 * @author admin
 */
public interface UserMapper extends BaseMapper<User> {

    /**
     * 获取全部用户
     * @return
     */
    List<User> getAllUser();
}

测试

@Test
public void testGetAllUserByMybatisPlus() throws IOException {
    InputStream stream = Resources.getResourceAsStream("mybatis-config.xml");
    SqlSessionFactory sqlSessionFactory = new MybatisSqlSessionFactoryBuilder().build(stream);
    SqlSession sqlSession = sqlSessionFactory.openSession();
    UserMapper mapper = sqlSession.getMapper(UserMapper.class);
    List<User> userList = mapper.selectList(null);
    for (User user : userList) {
        System.out.println(user);
    }
    sqlSession.close();
}

结果

image

2.3、spring + mybatis-plus 实现查询

User.java

package com.example.pojo;

import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

/**
 * @author admin
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
@TableName("tb_user")
public class User {
    private int id;
    private String userName;
    private String password;
    private String name;
    private Integer age;
    private String email;
}

UserMapper.java

package com.example.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.example.pojo.User;

/**
 * @author admin
 */
public interface UserMapper extends BaseMapper<User> {
}

jdbc.properties

jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/test?characterEncoding=utf8&useSSL=true&serverTimezone=UTC
jdbc.username=root
jdbc.password=123456

applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">

    <context:property-placeholder location="classpath:jdbc.properties"/>

    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close">
        <property name="driverClassName" value="${jdbc.driver}"/>
        <property name="url" value="${jdbc.url}"/>
        <property name="username" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
        <property name="maxActive" value="10"/>
        <property name="minIdle" value="5"/>
    </bean>

    <bean id="sqlSessionFactory" class="com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource"/>
    </bean>

    <!--mapper接口扫描器-->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="basePackage" value="com.example.mapper"/>
    </bean>

</beans>

测试

package com.example.mapper;

import com.example.pojo.User;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import java.util.List;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class UserMapperTest {

    @Autowired
    private SqlSessionFactory sqlSessionFactory;

    @Test
    public void testGetAllUser(){
        SqlSession sqlSession = sqlSessionFactory.openSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        List<User> userList = mapper.selectList(null);
        for (User user : userList) {
            System.out.println(user);
        }
        sqlSession.close();
    }
}

结果

image

2.4、springboot + mybatis-plus 实现查询

项目结构

image

maven依赖

<dependencies>
    <!-- https://mvnrepository.com/artifact/com.baomidou/mybatis-plus-boot-starter -->
    <dependency>
        <groupId>com.baomidou</groupId>
        <artifactId>mybatis-plus-boot-starter</artifactId>
        <version>3.3.2</version>
    </dependency>

    <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-test -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter</artifactId>
    </dependency>

    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <scope>runtime</scope>
    </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>
</dependencies>

application.properties

spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/test?characterEncoding=utf8&useSSL=true&serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=123456

User.java

package com.example.pojo;

import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

/**
 * @author admin
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
@TableName("tb_user")
public class User {
    private int id;
    private String userName;
    private String password;
    private String name;
    private Integer age;
    private String email;
}

UserMapper.java

package com.example.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.example.pojo.User;
import org.apache.ibatis.annotations.Mapper;

/**
 * @author admin
 */
public interface UserMapper extends BaseMapper<User> {
}

SpringBoot启动类

package com.example;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

/**
 * @author admin
 */
@SpringBootApplication
@MapperScan("com.example.mapper")
public class MybatisPlusSpringbootApplication {

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

}

测试

package com.example;

import com.example.mapper.UserMapper;
import com.example.pojo.User;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import java.util.List;

@SpringBootTest
class MybatisPlusSpringbootApplicationTests {

    @Autowired(required = false)
    private UserMapper userMapper;

    @Test
    void contextLoads() {
        List<User> userList = userMapper.selectList(null);
        for (User user : userList) {
            System.out.println(user);
        }
    }

}

结果

image

3、通用CRUD

3.1、插入

User.java

package com.example.pojo;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

/**
 * @author admin
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
@TableName("tb_user")
public class User {
    @TableId(type = IdType.AUTO)
    private int id;
    private String userName;
    private String password;
    private String name;
    private Integer age;
    private String email;
}

测试

@Test
public void testInsert(){
    User user = new User();
    user.setUserName("simayi");
    user.setPassword("666666");
    user.setName("司马懿");
    user.setAge(31);
    user.setEmail("simayi@test.com");
    int row = userMapper.insert(user);
    System.out.println("数据库中受影响的行数: "+row);
    //自增后的id会回填到对象中
    int id = user.getId();
    System.out.println("自增长后的id值: "+id);
}

3.2、@TableField

在mybatis-plus中通过@TableField注解可以指定字段的一些属性,常常解决的问题有2个:

  1. 对象中的属性名和字段名不一致的问题(非驼峰)
  2. 对象中的属性字段在表中不存在的问题

数据库中的tb_user表

image

实体映射User

解决问题1:

package com.example.pojo;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

/**
 * @author admin
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
@TableName("tb_user")
public class User {
    @TableId(type = IdType.AUTO)
    private int id;
    private String userName;
    private String password;
    private String name;
    private Integer age;
    //指定数据库中的字段
    @TableField("email")
    private String mail;
}

解决问题2:

package com.example.pojo;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

/**
 * @author admin
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
@TableName("tb_user")
public class User {
    @TableId(type = IdType.AUTO)
    private int id;
    private String userName;
    private String password;
    private String name;
    private Integer age;
    private String email;

    /**
     * 表明该属性在数据库中不存在
     */
    @TableField(exist = false)
    private String address;
}

查询时不返回指定字段的值

package com.example.pojo;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

/**
 * @author admin
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
@TableName("tb_user")
public class User {
    @TableId(type = IdType.AUTO)
    private int id;
    private String userName;
    
    /**
     * 查询时不返回该字段的值
     */
    @TableField(select = false)
    private String password;
    private String name;
    private Integer age;
    private String email;
}

3.3、更新

3.3.1、根据id更新

测试

@Test
public void testUpdateById(){
    User user = new User();
    user.setId(7);
    user.setPassword("777777");
    int row = userMapper.updateById(user);
    System.out.println("数据库中受影响的行数: "+row);
    testSelectById();
}

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

结果

image

3.3.2、根据条件更新

测试

方法一:

@Test
public void testUpdateByCondition_1(){
    User user = new User();
    user.setAge(18);
    QueryWrapper<User> wrapper = new QueryWrapper<>();
    //匹配user_name等于zhangsan的用户数据
    wrapper.eq("user_name","zhangsan");
    int row = userMapper.update(user, wrapper);
    System.out.println("数据库中受影响的行数: "+row);
}

方法二:

@Test
public void testUpdateByCondition_2(){
    UpdateWrapper<User> wrapper = new UpdateWrapper<>();
    wrapper.set("age",18).eq("user_name","zhangsan");
    int row = userMapper.update(null, wrapper);
    System.out.println("数据库中受影响的行数: "+row);
}

3.4、删除

3.4.1、根据id删除

测试

@Test
public void testDeleteById(){
    int row = userMapper.deleteById(100);
    System.out.println("数据库中受影响的行数: "+row);
}

3.4.2、根据条件删除

测试

方法一:

@Test
public void testDeleteByMap(){
    Map<String,Object> map=new HashMap<>();
    map.put("user_name","zhangsan");
    map.put("password","999999");
    //根据map删除数据,多条件之间是and关系
    int row = userMapper.deleteByMap(map);
    System.out.println("数据库中受影响的行数: "+row);
}

方法二:

@Test
public void testDelete_1(){
    QueryWrapper<User> wrapper = new QueryWrapper<>();
    wrapper.eq("user_name","zhangsan").eq("password","999999");
    int row = userMapper.delete(wrapper);
    System.out.println("数据库中受影响的行数: "+row);
}

方法三:

@Test
public void testDelete_2(){
    User user = new User();
    user.setUserName("zhangsan");
    user.setPassword("000000");
    QueryWrapper<User> wrapper = new QueryWrapper<>(user);
    int row = userMapper.delete(wrapper);
    System.out.println("数据库中受影响的行数: "+row);
}

3.4.3、根据id批量删除

测试

@Test
public void testDeleteBatchIds(){
    //根据id批量删除记录
    int row = userMapper.deleteBatchIds(Arrays.asList(100, 200, 300, 400, 500));
    System.out.println("数据库中受影响的行数: "+row);
}

3.5、查询

3.5.1、根据id查询

测试

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

3.5.2、根据id批量查询

测试

@Test
public void testSelectBatchIds(){
    List<User> userList = userMapper.selectBatchIds(Arrays.asList(1, 2, 3, 100));
    for (User user : userList) {
        System.out.println(user);
    }
}

3.5.3、根据条件查询

根据条件查询单条记录

@Test
public void testSelectOne(){
    QueryWrapper<User> wrapper = new QueryWrapper<>();
    wrapper.eq("user_name","zhaoliu");
    User user = userMapper.selectOne(wrapper);
    System.out.println(user);
}

注意:若查询结果包含多条记录则报错

根据条件查询多条记录

@Test
public void testSelectList(){
    QueryWrapper<User> wrapper = new QueryWrapper<>();
    //wrapper.gt("age",25);
    //查询邮箱中包含z的用户
    wrapper.like("email","z");
    List<User> userList = userMapper.selectList(wrapper);
    for (User user : userList) {
        System.out.println(user);
    }
}

3.5.4、查询记录的条数

测试

@Test
public void testSelectCount(){
    QueryWrapper<User> wrapper = new QueryWrapper<>();
    //查询年龄大于20岁的用户
    wrapper.gt("age",20);
    Integer count = userMapper.selectCount(wrapper);
    System.out.println("年龄大于20岁的用户有"+count+"个");
}

3.5.5、分页查询

MybatisPlusConfig.java

package com.example;

import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @author admin
 */
@Configuration
@MapperScan("com.example.mapper")
public class MybatisPlusConfig {

    /**
     * 配置分页插件
     * @return
     */
    @Bean
    public PaginationInterceptor paginationInterceptor(){
        return new PaginationInterceptor();
    }
}

测试

@Test
public void testSelectPage(){
    //查询第一页,每页3条数据
    Page<User> page = new Page<>(1,3);
    QueryWrapper<User> wrapper = new QueryWrapper<>();
    wrapper.gt("age","20");
    Page<User> userPage = userMapper.selectPage(page, wrapper);
    System.out.println("数据总条数: "+userPage.getTotal());
    System.out.println("数据总页数: "+userPage.getPages());
    System.out.println("当前页数: "+userPage.getCurrent());
    List<User> userList = userPage.getRecords();
    for (User user : userList) {
        System.out.println(user);
    }
}

4、配置

4.1、configLocation

springboot:

mybatis-plus.config-location=classpath:mybatis-config.xml

springmvc:

<bean id="sqlSessionFactory" class="com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean">
	<property name="configLocation" value="classpath:mybatis-config.xml"/>
</bean>

4.2、mapperLocations

springboot:

mybatis-plus.mapper-locations=classpath:mybatis/*.xml

springmvc:

<bean id="sqlSessionFactory" class="com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean">
	<property name="mapperLocations" value="classpath:mybatis/*.xml"/>
</bean>

4.3、typeAliasesPackage

springboot:

mybatis-plus.type-aliases-package=com.example.pojo

springmvc:

<bean id="sqlSessionFactory" class="com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean">
	<property name="typeAliasesPackage" value="com.example.pojo"/>
</bean>

4.4、mapUnderscoreToCamelCase

  • 类型:boolean
  • 默认值:true

是否开启自动驼峰命名规则映射,即从经典数据库列名a_column(下划线命名)到经典Java属性名aColumn(驼峰命名)的类似映射。

注意:

此属性在MyBatis中原默认值为false,在MyBatis-Plus中,此属性也将用于生成最终的sql的select body

如果你的数据库命名符合规则则无需使用@TableField注解指定数据库字段名

mybatis-plus.configuration.*和mybatis-plus.config-location不能同时出现在配置文件中

springboot:

mybatis-plus.configuration.map-underscore-to-camel-case=false

4.5、cacheEnabled

  • 类型:boolean
  • 默认值:true

全局地开启或关闭配置文件中的所有映射器已经配置的任何缓存,默认为true。

springboot:

mybatis-plus.configuration.cache-enabled=false

4.6、idType

  • 类型:com.baomidou.mybatisplus.annotation.IdType
  • 默认值:ID_WORKER

全局默认主键类型,设置后,即可省略实体对象中的@TableId(type = IdType.AUTO)配置

springboot:

mybatis-plus.global-config.db-config.id-type=auto

springmvc:

<bean id="sqlSessionFactory" class="com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean">
	<property name="globalConfig">
    	<bean class="com.baomidou.mybatisplus.core.config.GlobalConfig">
        	<property name="dbConfig">
            	<bean class="com.baomidou.mybatisplus.core.config.GlobalConfig$DbConfig">
                	<property name="idType" value="AUTO"/>
                </bean>
            </property>
        </bean>
    </property>
</bean>

4.7、tablePrefix

  • 类型:String
  • 默认值:null

表名前缀,全局配置后可省略@TableName()配置

springboot:

mybatis-plus.global-config.db-config.table-prefix=tb_

springmvc:

<bean id="sqlSessionFactory" class="com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean">
	<property name="globalConfig">
    	<bean class="com.baomidou.mybatisplus.core.config.GlobalConfig">
        	<property name="dbConfig">
            	<bean class="com.baomidou.mybatisplus.core.config.GlobalConfig$DbConfig">
                	<property name="tablePrefix" value="tb_"/>
                </bean>
            </property>
        </bean>
    </property>
</bean>

5、条件构造器

说明:

  • 以下出现的第一个入参boolean condition表示该条件是否加入最后生成的sql中,例如:query.like(StringUtils.isNotBlank(name), Entity::getName, name) .eq(age!=null && age >= 0, Entity::getAge, age)
  • 以下代码块内的多个方法均为从上往下补全个别boolean类型的入参,默认为true
  • 以下出现的泛型Param均为Wrapper的子类实例(均具有AbstractWrapper的所有方法)
  • 以下方法在入参中出现的R为泛型,在普通wrapper中是String,在LambdaWrapper中是函数(例:Entity::getId,Entity为实体类,getId为字段idgetMethod)
  • 以下方法入参中的R column均表示数据库字段,当R具体类型为String时则为数据库字段名(字段名是数据库关键字的自己用转义符包裹!)!而不是实体类数据字段名!!!,另当R具体类型为SFunction时项目runtime不支持eclipse自家的编译器!!!
  • 以下举例均为使用普通wrapper,入参为MapList的均以json形式表现!
  • 使用中如果入参的Map或者List,则不会加入最后生成的sql中!!!
  • 有任何疑问就点开源码看,看不懂函数点击我学习新知识(opens new window)

警告:

不支持以及不赞成在 RPC 调用中把 Wrapper 进行传输

  1. wrapper 很重
  2. 传输 wrapper 可以类比为你的 controller 用 map 接收值(开发一时爽,维护火葬场)
  3. 正确的 RPC 调用姿势是写一个 DTO 进行传输,被调用方再根据 DTO 执行相应的操作
  4. 我们拒绝接受任何关于 RPC 传输 Wrapper 报错相关的 issue 甚至 pr

AbstractWrapper

说明:

QueryWrapper(LambdaQueryWrapper) 和 UpdateWrapper(LambdaUpdateWrapper) 的父类
用于生成 sql 的 where 条件, entity 属性也用于生成 sql 的 where 条件
注意: entity 生成的 where 条件与 使用各个 api 生成的 where 条件没有任何关联行为

5.1、allEq

测试

@Test
public void testAllEq(){
    Map<String,Object> map=new HashMap<>();
    map.put("name","李四");
    map.put("age",20);
    map.put("password",null);
    QueryWrapper<User> wrapper = new QueryWrapper<>();
    //null值作为查询条件:SELECT id,user_name,password,name,age,email FROM tb_user WHERE (password IS NULL AND name = ? AND age = ?)
    //wrapper.allEq(map);
    //null值不作为查询条件:SELECT id,user_name,password,name,age,email FROM tb_user WHERE (name = ? AND age = ?)
    //wrapper.allEq(map,false);
    //SELECT id,user_name,password,name,age,email FROM tb_user WHERE (age = ?) 
    wrapper.allEq((k,v)->(k.equals("age") || k.equals("id")), map);
    List<User> userList = userMapper.selectList(wrapper);
    for (User user : userList) {
        System.out.println(user);
    }
}

5.2、基本比较操作

  • eq:等于 =
  • ne:不等于 <>
  • gt:大于 >
  • ge:大于等于 >=
  • lt:小于 <
  • le:小于等于 <=
  • between:between 值1 and 值2
  • notBetween:not between 值1 and 值2
  • in:字段 in (value.get(0), value.get(1), ...)
  • notIn:字段 not in (v0, v1, ...)

测试

@Test
public void testBasicConditionStructure(){
    QueryWrapper<User> wrapper = new QueryWrapper<>();
    //SELECT id,user_name,password,name,age,email FROM tb_user WHERE (password = ? AND age >= ? AND name IN (?,?,?)) 
    wrapper.eq("password","222222")
            .ge("age",20)
            .in("name","张三","李四","王五");
    List<User> userList = userMapper.selectList(wrapper);
    for (User user : userList) {
        System.out.println(user);
    }
}

5.3、模糊查询

  • like
    • like '%值%'
    • 例:like("name", "王") ---> name like '%王%'
  • notLike
    • not like '%值%'
    • 例:notLike("name", "王") ---> name not like '%王%'
  • likeLeft
    • like '%值'
    • 例:likeLeft("name", "王") ---> name like '%王'
  • likeRight
    • like '值%'
    • 例:likeRight("name", "王") ---> name like '王%'

测试

@Test
public void testLike(){
    QueryWrapper<User> wrapper = new QueryWrapper<>();
    wrapper.likeLeft("name","五");
    List<User> userList = userMapper.selectList(wrapper);
    for (User user : userList) {
        System.out.println(user);
    }
}

5.4、排序

  • orderBy
    • 排序:order by 字段, ...
    • 例:orderBy(true, true, "id", "name") ---> order by id ASC,name ASC
  • orderByAsc
    • 排序:order by 字段, ... ASC
    • 例:orderByAsc("id", "name") ---> order by id ASC,name ASC
  • orderByDesc
    • 排序:order by 字段, ... desc
    • 例:orderByDesc("id", "name") ---> order by id desc,name desc

测试

@Test
public void testOrderByDesc(){
    QueryWrapper<User> wrapper = new QueryWrapper<>();
    //按照年龄倒序排序:SELECT id,user_name,password,name,age,email FROM tb_user ORDER BY age DESC 
    wrapper.orderByDesc("age");
    List<User> userList = userMapper.selectList(wrapper);
    for (User user : userList) {
        System.out.println(user);
    }
}

5.5、逻辑查询

  • or
    • 拼接 or
    • 主动调用or表示紧接着下一个方法不是用and连接!(不调用or则默认为使用and连接)
  • and
    • and 嵌套
    • 例:and(i -> i.eq("name", "张三").gt("age", 20)) ---> and (name = '张三' and age > 20)

测试

@Test
public void testOr(){
    QueryWrapper<User> wrapper = new QueryWrapper<>();
    //SELECT id,user_name,password,name,age,email FROM tb_user WHERE (name = ? OR age = ?) 
    wrapper.eq("name","王五").or().eq("age",21);
    List<User> userList = userMapper.selectList(wrapper);
    for (User user : userList) {
        System.out.println(user);
    }
}

5.6、select

在mybatis-plus查询中,默认查询所有的字段,如果有需要也可以通过select方法进行指定字段。

测试

@Test
public void testSelect(){
    QueryWrapper<User> wrapper = new QueryWrapper<>();
    //SELECT id,name,age FROM tb_user 
    wrapper.select("id","name","age");
    List<User> userList = userMapper.selectList(wrapper);
    for (User user : userList) {
        System.out.println(user);
    }
}

6、ActiveRecord

ActiveRecord(简称AR)一直广受动态语言(PHP、Ruby等)的喜爱,而Java作为准静态语言,对于ActiveRecord往往只能感叹其优雅,所以我们也在AR道路上进行了一定的探索。

什么是ActiveRecord?

ActiveRecord也属于ORM(对象关系映射)层,由Reils最早提出,遵循标准的ORM模型:表映射到记录,记录映射到对象,字段映射到对象属性。配合遵循的命名和配置惯例,能够很大程度的快速实现模型的操作,而且简洁易懂。

ActiveRecord的主要思想是:

  • 每一个数据库表对应创建一个类,类的每一个对象实例对应于数据库中表的一行记录;通常表的每个字段在类中都有相应的Field;
  • ActiveRecord同时负责把自己持久化,在ActiveRecord中封装了对数据库的访问,即CURD;
  • ActiveRecord是一种领域模型(Domain Model),封装了部分业务逻辑;

6.1、根据主键查询

User.java

package com.example.pojo;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.extension.activerecord.Model;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

/**
 * @author admin
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
@TableName("tb_user")
public class User extends Model<User> {
    @TableId(type = IdType.AUTO)
    private int id;
    private String userName;
    private String password;
    private String name;
    private Integer age;
    private String email;
}

测试

package com.example;

import com.example.pojo.User;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
public class UserTest {

    @Test
    public void testSelectById(){
        User user = new User();
        user.setId(3);
        User userById = user.selectById();
        System.out.println(userById);
    }
}

结果

image

6.2、插入

User.java

package com.example.pojo;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.extension.activerecord.Model;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

/**
 * @author admin
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
@TableName("tb_user")
public class User extends Model<User> {
    @TableId(type = IdType.AUTO)
    private int id;
    private String userName;
    private String password;
    private String name;
    private Integer age;
    private String email;
}

测试

@Test
public void testInsert(){
    User user = new User();
    user.setUserName("pangtong");
    user.setPassword("888888");
    user.setName("庞统");
    user.setAge(36);
    user.setEmail("pangtong@test.com");
    boolean isInsert = user.insert();
    System.out.println("插入是否成功: "+isInsert);
}

6.3、更新

6.3.1、根据id更新

@Test
public void testUpdateById(){
    User user = new User();
    //查询条件
    user.setId(10);
    //更新的数据
    user.setAge(100);
    boolean isUpdate = user.updateById();
    System.out.println("更新是否成功: "+isUpdate);
}

6.3.2、根据条件更新

@Test
public void testUpdate(){
    User user = new User();
    UpdateWrapper<User> wrapper = new UpdateWrapper<>();
    wrapper.eq("name","太史特").set("age",100);
    boolean isUpdate = user.update(wrapper);
    System.out.println("更新是否成功: "+isUpdate);
}

6.4、删除

6.4.1、根据id删除

@Test
public void testDeleteById(){
    User user = new User();
    boolean isDelete = user.deleteById(100);
    System.out.println("删除是否成功: "+isDelete);
}

6.4.2、根据条件删除

@Test
public void testDelete(){
    User user = new User();
    QueryWrapper<User> wrapper = new QueryWrapper<>();
    wrapper.eq("name","太史特");
    boolean isDelete = user.delete(wrapper);
    System.out.println("删除是否成功: "+isDelete);
}

6.5、根据条件查询

@Test
public void testSelectList(){
    User user = new User();
    QueryWrapper<User> wrapper = new QueryWrapper<>();
    //查询年龄大于等于30岁的用户
    wrapper.ge("age",30);
    List<User> userList = user.selectList(wrapper);
    for (User user1 : userList) {
        System.out.println(user1);
    }
}
posted @ 2021-11-13 10:44  (x²+y²-1)³=x²y³  阅读(75)  评论(0编辑  收藏  举报