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、框架结构
2、快速入门
2.1、mybatis实现查询
项目结构
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();
}
}
结果
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();
}
结果
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();
}
}
结果
2.4、springboot + mybatis-plus 实现查询
项目结构
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);
}
}
}
结果
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个:
- 对象中的属性名和字段名不一致的问题(非驼峰)
- 对象中的属性字段在表中不存在的问题
数据库中的tb_user表
实体映射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);
}
结果
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
为字段id
的getMethod) - 以下方法入参中的
R column
均表示数据库字段,当R
具体类型为String
时则为数据库字段名(字段名是数据库关键字的自己用转义符包裹!)!而不是实体类数据字段名!!!,另当R
具体类型为SFunction
时项目runtime不支持eclipse自家的编译器!!! - 以下举例均为使用普通wrapper,入参为
Map
和List
的均以json
形式表现! - 使用中如果入参的
Map
或者List
为空,则不会加入最后生成的sql中!!! - 有任何疑问就点开源码看,看不懂函数的点击我学习新知识(opens new window)
警告:
不支持以及不赞成在 RPC 调用中把 Wrapper 进行传输
- wrapper 很重
- 传输 wrapper 可以类比为你的 controller 用 map 接收值(开发一时爽,维护火葬场)
- 正确的 RPC 调用姿势是写一个 DTO 进行传输,被调用方再根据 DTO 执行相应的操作
- 我们拒绝接受任何关于 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);
}
}
结果
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);
}
}