黑马程序员笔记----Mybatis-Plus使用
一、纯Mybatis与Mybatis-Plus整合。
1.导入依赖
-
-
<project xmlns="http://maven.apache.org/POM/4.0.0"
-
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-
<modelVersion>4.0.0</modelVersion>
-
-
<groupId>org.example</groupId>
-
<artifactId>cn.itcast.mp</artifactId>
-
<packaging>pom</packaging>
-
<version>1.0-SNAPSHOT</version>
-
<modules>
-
<module>itcast-mybatis-plus-simple</module>
-
<module>itcast-mabatis-plus-spring</module>
-
</modules>
-
-
<properties>
-
<maven.compiler.source>8</maven.compiler.source>
-
<maven.compiler.target>8</maven.compiler.target>
-
</properties>
-
-
<dependencies>
-
<!-- mybatis-plus插件依赖 -->
-
<dependency>
-
<groupId>com.baomidou</groupId>
-
<artifactId>mybatis-plus</artifactId>
-
<version>3.1.1</version>
-
</dependency>
-
-
<!-- MySql -->
-
<dependency>
-
<groupId>mysql</groupId>
-
<artifactId>mysql-connector-java</artifactId>
-
<version>8.0.25</version>
-
</dependency>
-
<!-- 连接池 -->
-
<dependency>
-
<groupId>com.alibaba</groupId>
-
<artifactId>druid</artifactId>
-
<version>1.1.24</version>
-
</dependency>
-
-
<!--简化bean代码的工具包-->
-
<dependency>
-
<groupId>org.projectlombok</groupId>
-
<artifactId>lombok</artifactId>
-
<optional>true</optional>
-
<version>1.18.4</version>
-
</dependency>
-
<dependency>
-
<groupId>junit</groupId>
-
<artifactId>junit</artifactId>
-
<version>4.12</version>
-
</dependency>
-
<dependency>
-
<groupId>org.slf4j</groupId>
-
<artifactId>slf4j-log4j12</artifactId>
-
<version>1.6.4</version>
-
</dependency>
-
</dependencies>
-
<build>
-
<plugins>
-
<plugin>
-
<groupId>org.apache.maven.plugins</groupId>
-
<artifactId>maven-compiler-plugin</artifactId>
-
<configuration>
-
<source>1.8</source>
-
<target>1.8</target>
-
</configuration>
-
</plugin>
-
</plugins>
-
</build>
-
</project>
2.创建配置文件
log4j.properties:
-
log4j.rootLogger=DEBUG,A1
-
-
log4j.appender.A1=org.apache.log4j.ConsoleAppender
-
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
-
log4j.appender.A1.layout.ConversionPattern=[%t] [%c]-[%p] %m%n
jdbc.properties:
-
jdbc.username=
-
jdbc.password=
-
jdbc.url=jdbc:mysql://localhost:3306/mabatis-puls
-
jdbc.driverClassName=com.mysql.jdbc.Driver
-
jdbc.initialSize=5
-
jdbc.maxActive=10
3.编写mybatis-config.xml文件:
-
-
-
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
-
"http://mybatis.org/dtd/mybatis-3-config.dtd">
-
<configuration>
-
<!-- 加载外部文件-->
-
<properties resource="jdbc.properties"></properties>
-
<!-- 数据源环境-->
-
<environments default="development">
-
<environment id="development">
-
<transactionManager type="JDBC"></transactionManager>
-
<dataSource type="POOLED">
-
<property name="driver" value="${jdbc.driverClassName}"></property>
-
<property name="url" value="${jdbc.url}"></property>
-
<property name="username" value="${jdbc.username}"></property>
-
<property name="password" value="${jdbc.password}"></property>
-
</dataSource>
-
</environment>
-
</environments>
-
<mappers>
-
<mapper resource="UserMapper.xml"></mapper>
-
</mappers>
-
</configuration>
4.编写User实体对象:(这里使用lombok进行了进化bean操作)
-
import com.baomidou.mybatisplus.annotation.TableName;
-
import lombok.AllArgsConstructor;
-
import lombok.Data;
-
import lombok.NoArgsConstructor;
-
-
/* 用lombok
-
* @Data :注解在类上;提供类所有属性的 getting 和 setting 方法,此外还提供了equals、canEqual、hashCode、toString 方法
-
@Setter:注解在属性上;为属性提供 setting 方法
-
@Getter:注解在属性上;为属性提供 getting 方法
-
@Log4j :注解在类上;为类提供一个 属性名为log 的 log4j 日志对象
-
@NoArgsConstructor:注解在类上;为类提供一个无参的构造方法
-
@AllArgsConstructor:注解在类上;为类提供一个全参的构造方法
-
* 在User对象中添加@TableName,指定数据库表名
-
*/
-
-
-
-
-
public class User {
-
private Long id;
-
private String user_name;
-
private String password;
-
private String name;
-
private Integer age;
-
private String email;
-
-
-
public String toString() {
-
return "User{"
-
"id=" id
-
", userName='" user_name '\''
-
", password='" password '\''
-
", name='" name '\''
-
", age=" age
-
", email='" email '\''
-
'}';
-
}
-
}
5.将UserMapper继承BaseMapper,将拥有了BaseMapper中的所有方法:
-
import cn.itcast.mp.pojo.User;
-
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
-
-
-
import java.util.List;
-
-
public interface UserMapper extends BaseMapper<User> {
-
public List<User> findAll();
-
-
}
6.使用MP中的MybatisSqlSessionFactoryBuilder进程构建
-
-
-
import cn.itcast.mp.mapper.UserMapper;
-
import cn.itcast.mp.pojo.User;
-
import com.baomidou.mybatisplus.core.MybatisSqlSessionFactoryBuilder;
-
import org.apache.ibatis.io.Resources;
-
import org.apache.ibatis.session.SqlSession;
-
import org.apache.ibatis.session.SqlSessionFactory;
-
-
import org.junit.Test;
-
-
import java.io.IOException;
-
import java.io.InputStream;
-
import java.util.List;
-
-
public class MybatistTest {
-
-
public void testFindAll() throws IOException {
-
InputStream resourceAsFile = Resources.getResourceAsStream("mybatis-config.xml");
-
//这里使用的是MP中的MybatisSqlSessionFactoryBuilder
-
SqlSessionFactory sqlSessionFactory = new MybatisSqlSessionFactoryBuilder().build(resourceAsFile);
-
SqlSession sqlSession = sqlSessionFactory.openSession();
-
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
-
-
// 可以调用BaseMapper中定义的方法
-
List<User> users = mapper.selectList(null);
-
System.out.println(users);
-
sqlSession.close();
-
-
}
-
}
注:
①如运行报错:
解决:在User对象中添加@TableName,指定数据库表名
二、Spring Mybatis MP
引入了Spring框架,数据源、构建等工作就交给了Spring管理。
1.导入依赖
-
-
<project xmlns="http://maven.apache.org/POM/4.0.0"
-
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-
<modelVersion>4.0.0</modelVersion>
-
-
<groupId>org.example</groupId>
-
<artifactId>cn.itcast.mp</artifactId>
-
<packaging>pom</packaging>
-
<version>1.0-SNAPSHOT</version>
-
<modules>
-
<module>itcast-mybatis-plus-simple</module>
-
<module>itcast-mabatis-plus-spring</module>
-
</modules>
-
-
<properties>
-
<maven.compiler.source>8</maven.compiler.source>
-
<maven.compiler.target>8</maven.compiler.target>
-
</properties>
-
-
<dependencies>
-
<!-- mybatis-plus插件依赖 -->
-
<dependency>
-
<groupId>com.baomidou</groupId>
-
<artifactId>mybatis-plus</artifactId>
-
<version>3.1.1</version>
-
</dependency>
-
-
<!-- MySql -->
-
<dependency>
-
<groupId>mysql</groupId>
-
<artifactId>mysql-connector-java</artifactId>
-
<version>8.0.25</version>
-
</dependency>
-
<!-- 连接池 -->
-
<dependency>
-
<groupId>com.alibaba</groupId>
-
<artifactId>druid</artifactId>
-
<version>1.1.24</version>
-
</dependency>
-
-
<!--简化bean代码的工具包-->
-
<dependency>
-
<groupId>org.projectlombok</groupId>
-
<artifactId>lombok</artifactId>
-
<optional>true</optional>
-
<version>1.18.4</version>
-
</dependency>
-
<dependency>
-
<groupId>junit</groupId>
-
<artifactId>junit</artifactId>
-
<version>4.12</version>
-
</dependency>
-
<dependency>
-
<groupId>org.slf4j</groupId>
-
<artifactId>slf4j-log4j12</artifactId>
-
<version>1.6.4</version>
-
</dependency>
-
<!--Spring相关坐标-->
-
<dependency>
-
<groupId>org.springframework</groupId>
-
<artifactId>spring-webmvc</artifactId>
-
<version>5.0.5.RELEASE</version>
-
</dependency>
-
<dependency>
-
<groupId>org.springframework</groupId>
-
<artifactId>spring-jdbc</artifactId>
-
<version>5.0.5.RELEASE</version>
-
</dependency>
-
<dependency>
-
<groupId>org.springframework</groupId>
-
<artifactId>spring-test</artifactId>
-
<version>5.0.5.RELEASE</version>
-
</dependency>
-
</dependencies>
-
<build>
-
<plugins>
-
<plugin>
-
<groupId>org.apache.maven.plugins</groupId>
-
<artifactId>maven-compiler-plugin</artifactId>
-
<configuration>
-
<source>1.8</source>
-
<target>1.8</target>
-
</configuration>
-
</plugin>
-
</plugins>
-
</build>
-
</project>
2.编写jdbc.properties
-
log4j.rootLogger=DEBUG,A1
-
-
log4j.appender.A1=org.apache.log4j.ConsoleAppender
-
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
-
log4j.appender.A1.layout.ConversionPattern=[%t] [%c]-[%p] %m%n
3. 编写applicationContext.xml
-
-
<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
-
http://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="url" value="${jdbc.url}"/>
-
<property name="username" value="${jdbc.username}"/>
-
<property name="password" value="${jdbc.password}"/>
-
<property name="driverClassName" value="${jdbc.driverClassName}"/>
-
<property name="maxActive" value="10"/>
-
<property name="minIdle" value="5"/>
-
</bean>
-
<!--这里使用MP提供的sessionFactory 完成MP和Spring的整合-->
-
<bean id="sessionFactory" class="com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean">
-
<property name="dataSource" ref="dataSource"/>
-
</bean>
-
-
<!--扫描mapper接口,使用的依然是Mybatis原生的扫描器-->
-
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
-
<property name="basePackage" value="mapper"/>
-
</bean>
-
-
</beans>
4.编写User对象以及UserMapper接口:
-
package pojo;
-
-
import com.baomidou.mybatisplus.annotation.TableName;
-
import lombok.AllArgsConstructor;
-
import lombok.Data;
-
import lombok.NoArgsConstructor;
-
-
-
-
-
-
public class User {
-
private Long id;
-
private String user_name;
-
private String password;
-
private String name;
-
private Integer age;
-
private String email;
-
-
-
}
-
package mapper;
-
-
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
-
import pojo.User;
-
-
/**
-
* @Description: // 类说明
-
* @ClassName: UserMapper // 类名
-
* @Author: 曾伟鸿 // 创建者
-
* @Date: 2022/1/30 11:59 // 时间
-
* @Version: 1.0 // 版本
-
*/
-
public interface UserMapper extends BaseMapper<User> {
-
-
}
5.测试
-
-
-
public class TestSpringMP {
-
-
-
private UserMapper userMapper;
-
-
-
public void testSelectList(){
-
List<User> users = this.userMapper.selectList(null);
-
for (User user : users) {
-
System.out.println(user);
-
}
-
}
-
}
三、SpringBoot Mybatis MP
使用SpringBoot将进一步的简化MP的整合,需要注意的是,使用SpringBoot需要继承parent。
1.导入依赖
-
-
<project xmlns="http://maven.apache.org/POM/4.0.0"
-
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-
<modelVersion>4.0.0</modelVersion>
-
-
<parent>
-
<groupId>org.springframework.boot</groupId>
-
<artifactId>spring-boot-starter-parent</artifactId>
-
<version>2.1.4.RELEASE</version>
-
</parent>
-
-
<groupId>cn.itcast.mp</groupId>
-
<artifactId>itcast-mp-springboot</artifactId>
-
<version>1.0-SNAPSHOT</version>
-
-
<dependencies>
-
<dependency>
-
<groupId>org.springframework.boot</groupId>
-
<artifactId>spring-boot-starter</artifactId>
-
<exclusions>
-
<exclusion>
-
<groupId>org.springframework.boot</groupId>
-
<artifactId>spring-boot-starter-logging</artifactId>
-
</exclusion>
-
</exclusions>
-
</dependency>
-
<dependency>
-
<groupId>org.springframework.boot</groupId>
-
<artifactId>spring-boot-starter-test</artifactId>
-
<scope>test</scope>
-
</dependency>
-
-
<!--简化代码的工具包-->
-
<dependency>
-
<groupId>org.projectlombok</groupId>
-
<artifactId>lombok</artifactId>
-
<optional>true</optional>
-
</dependency>
-
<!--mybatis-plus的springboot支持-->
-
<dependency>
-
<groupId>com.baomidou</groupId>
-
<artifactId>mybatis-plus-boot-starter</artifactId>
-
<version>3.1.1</version>
-
</dependency>
-
<!--mysql驱动-->
-
<dependency>
-
<groupId>mysql</groupId>
-
<artifactId>mysql-connector-java</artifactId>
-
<version>8.0.25</version>
-
</dependency>
-
<dependency>
-
<groupId>org.slf4j</groupId>
-
<artifactId>slf4j-log4j12</artifactId>
-
</dependency>
-
-
</dependencies>
-
-
<build>
-
<plugins>
-
<plugin>
-
<groupId>org.springframework.boot</groupId>
-
<artifactId>spring-boot-maven-plugin</artifactId>
-
</plugin>
-
</plugins>
-
</build>
-
-
-
</project>
2.编写配置文件
log4j.properties:
-
log4j.rootLogger=DEBUG,A1
-
-
log4j.appender.A1=org.apache.log4j.ConsoleAppender
-
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
-
log4j.appender.A1.layout.ConversionPattern=[%t] [%c]-[%p] %m%n
3.编写application.properties
-
spring.application.name = itcast-mp-springboot
-
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
-
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/mp?
-
useUnicode=true&characterEncoding=utf8&autoReconnect=true&allowMultiQueries=true&useSSL=false
-
spring.datasource.username=root
-
spring.datasource.password=Zwh1174946082!
4.编写pojo
-
-
import com.baomidou.mybatisplus.annotation.TableName;
-
import lombok.AllArgsConstructor;
-
import lombok.Data;
-
import lombok.NoArgsConstructor;
-
-
-
-
-
-
-
public class User {
-
private Long id;
-
private String userName;
-
private String password;
-
private String name;
-
private Integer age;
-
private String email;
-
}
5.编写mapper
-
import cn.itcast.mp.pojo.User;
-
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
-
-
public interface UserMapper extends BaseMapper<User> {
-
}
6.编写启动类
-
package cn.itcast.mp;
-
import org.mybatis.spring.annotation.MapperScan;
-
import org.springframework.boot.SpringApplication;
-
import org.springframework.boot.WebApplicationType;
-
import org.springframework.boot.autoconfigure.SpringBootApplication;
-
import org.springframework.boot.builder.SpringApplicationBuilder;
-
-
//设置mapper接口的扫描包
-
-
public class MyApplication {
-
-
public static void main(String[] args) {
-
SpringApplication.run(MyApplication.class, args);
-
}
-
}
7.编写测试
-
import cn.itcast.mp.mapper.UserMapper;
-
import cn.itcast.mp.pojo.User;
-
import org.junit.Test;
-
import org.junit.runner.RunWith;
-
import org.springframework.beans.factory.annotation.Autowired;
-
import org.springframework.boot.test.context.SpringBootTest;
-
import org.springframework.test.context.junit4.SpringRunner;
-
import java.util.List;
-
-
-
-
public class UserMapperTest {
-
-
-
private UserMapper userMapper;
-
-
-
public void testSelect() {
-
-
List<User> userList = userMapper.selectList(null);
-
for (User user : userList) {
-
System.out.println(user);
-
}
-
}
-
}
四、通用CRUD详解
1)注解详解
1.设置id的生成策略——@TableId详解
@TableId 是设置id的生成策略
①AUTO---数据库ID自增
②NONE---该类型为未设置主键类型
③INPUT---用户输入ID ****该类型可以通过自己注册自动填充插件进行填充*****
以下3种类型、只有当插入对象ID 为空,才自动填充。
①ID_WORKER---全局唯一ID (idWorker)
②UUID---全局唯一ID (UUID)
③ID_WORKER_STR---字符串全局唯一ID (idWorker 的字符串表示)
例如:
2.@TableField
在MP中通过@TableField注解可以指定字段的一些属性,常常解决的问题有3个:
1、对象中的属性名和字段名不一致的问题(非驼峰)
2、对象中的属性字段在表中不存在的问题
3、不希望某个属性值出现在查询结果中
2) 增删改查操作
1.插入操作
测试用例:
-
import cn.itcast.mp.mapper.UserMapper;
-
import cn.itcast.mp.pojo.User;
-
import org.junit.Test;
-
import org.junit.runner.RunWith;
-
import org.springframework.beans.factory.annotation.Autowired;
-
import org.springframework.boot.test.context.SpringBootTest;
-
import org.springframework.test.context.junit4.SpringRunner;
-
-
import java.util.List;
-
-
-
-
public class TestUserMapper {
-
-
-
private UserMapper userMapper;
-
-
-
public void testInsert() {
-
User user = new User();
-
user.setMail("2@itcast.cn");
-
user.setAge(301);
-
user.setUserName("caocao1");
-
user.setName("曹操1");
-
user.setPassword("123456");
-
user.setAddress("北京");
-
-
int result = this.userMapper.insert(user); //result数据库受影响的行数
-
System.out.println("result => " result);
-
-
//获取自增长后的id值, 自增长后的id值会回填到user对象中
-
System.out.println("id => " user.getId());
-
}
2.更新操作
①根据id更新
方法定义:
/** * 根据 ID 修改 * * @param entity 实体对象 */ int updateById(; T entity)映射出来的SQL语句:UPDATE tb_user SET age=? WHERE id=?
-
-
-
-
public class TestUserMapper {
-
-
-
private UserMapper userMapper;
-
-
-
public void testUpdateById() {
-
User user = new User();
-
user.setId(1L); //条件,根据id更新
-
user.setAge(19); //更新的字段
-
user.setPassword("666666");
-
-
int result = this.userMapper.updateById(user);
-
System.out.println("result => " result);
-
}
-
}
②根据条件更新
方法定义:
/** * 根据 whereEntity 条件,更新记录 * * @param entity 实体对象 (set 条件值,可以为 null) * @param updateWrapper 实体对象封装操作类(可以为 null,里面的 entity 用于生成 where 语句) */ int update( T entity, Wrapper<T> updateWrapper);映射出来的SQL语句: UPDATE tb_user SET age=? WHERE id = ?
-
import cn.itcast.mp.mapper.UserMapper;
-
import cn.itcast.mp.pojo.User;
-
import com.baomidou.mybatisplus.core.conditions.Wrapper;
-
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
-
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
-
import net.minidev.json.writer.UpdaterMapper;
-
import org.junit.Test;
-
import org.junit.runner.RunWith;
-
import org.springframework.beans.factory.annotation.Autowired;
-
import org.springframework.boot.test.context.SpringBootTest;
-
import org.springframework.test.context.junit4.SpringRunner;
-
-
import java.util.List;
-
-
-
-
public class UserMapperTest {
-
-
-
private UserMapper userMapper;
-
-
-
//通过 QueryWrapper进行更新
-
-
public void testUpdate() {
-
User user = new User();
-
user.setAge(20); //更新的字段
-
user.setPassword("8888888");
-
-
//更新条件
-
QueryWrapper<User> wrapper = new QueryWrapper<>();
-
wrapper.eq("user_name", "zhangsan"); //匹配user_name = zhangsan 的用户数据
-
-
//根据条件做更新
-
int result = this.userMapper.update(user, wrapper);
-
System.out.println("result => " result);
-
}
-
-
-
//或者,通过UpdateWrapper进行更新
-
-
public void testUpdate2() {
-
-
UpdateWrapper<User> wrapper = new UpdateWrapper<>();
-
wrapper.set("age", 21).set("password", "999999") //更新的字段,设置的是字段的名字,而不是实体的属性
-
.eq("user_name", "zhangsan"); //更新的条件
-
-
//根据条件做更新
-
int result = this.userMapper.update(null, wrapper);
-
System.out.println("result => " result);
-
}
-
-
}
-
3.删除操作
①通过id删除---deleteById
方法定义:
/** * 根据 ID 删除 * * @param id 主键ID */ int deleteById(Serializable id);映射出来的SQL语句:DELETE FROM tb_user WHERE id=?
-
import cn.itcast.mp.mapper.UserMapper;
-
import org.junit.Test;
-
import org.junit.runner.RunWith;
-
import org.springframework.beans.factory.annotation.Autowired;
-
import org.springframework.boot.test.context.SpringBootTest;
-
import org.springframework.test.context.junit4.SpringRunner;
-
-
-
-
public class UserMapperTest {
-
-
-
private UserMapper userMapper;
-
-
-
public void testDeleteById(){
-
// 根据id删除数据
-
int result = this.userMapper.deleteById(9L);
-
System.out.println("result => " result);
-
}
-
}
②根据id批量删除数据---deleteBatchIds
方法定义:
/** * 删除(根据ID 批量删除) * * @param idList 主键ID列表(不能为 null 以及 empty) */ int deleteBatchIds( Collection<? extends Serializable> idList);映射出来的SQL语句:DELETE FROM tb_user WHERE id IN ( ? , ? , ? )
-
import cn.itcast.mp.mapper.UserMapper;
-
import org.junit.Test;
-
import org.junit.runner.RunWith;
-
import org.springframework.beans.factory.annotation.Autowired;
-
import org.springframework.boot.test.context.SpringBootTest;
-
import org.springframework.test.context.junit4.SpringRunner;
-
import java.util.Arrays;
-
-
-
-
public class UserMapperTest {
-
-
-
private UserMapper userMapper;
-
-
-
-
public void testDeleteBatchIds(){
-
// 根据id批量删除数据
-
int result = this.userMapper.deleteBatchIds(Arrays.asList(10L, 11L));
-
System.out.println("result => " result);
-
}
③通过map封装条件删除---deleteByMap
方法定义:
/** * 根据 columnMap 条件,删除记录 * * @param columnMap 表字段 map 对象 */ int deleteByMap(; Map<String, Object> columnMap)映射出来的SQL语句: DELETE FROM tb_user WHERE name = ? AND age = ?
-
import cn.itcast.mp.mapper.UserMapper;
-
import org.junit.Test;
-
import org.junit.runner.RunWith;
-
import org.springframework.beans.factory.annotation.Autowired;
-
import org.springframework.boot.test.context.SpringBootTest;
-
import org.springframework.test.context.junit4.SpringRunner;
-
import java.util.HashMap;
-
import java.util.Map;
-
-
-
-
public class UserMapperTest {
-
-
-
private UserMapper userMapper;
-
-
-
public void testDeleteByMap(){
-
-
Map<String,Object> map = new HashMap<>();
-
map.put("user_name", "zhangsan");
-
map.put("password", "999999");
-
-
// 根据map删除数据,多条件之间是and关系
-
int result = this.userMapper.deleteByMap(map);
-
System.out.println("result => " result);
-
}
④通过实体对象封装条件删除---delete
方法定义:
/** * 根据 entity 条件,删除记录 * * @param wrapper 实体对象封装操作类(可以为 null) */ int delete(; Wrapper<T> wrapper)映射出来的SQL语句: DELETE FROM tb_user WHERE name=? AND age=?
-
import cn.itcast.mp.mapper.UserMapper;
-
import cn.itcast.mp.pojo.User;
-
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
-
import org.junit.Test;
-
import org.junit.runner.RunWith;
-
import org.springframework.beans.factory.annotation.Autowired;
-
import org.springframework.boot.test.context.SpringBootTest;
-
import org.springframework.test.context.junit4.SpringRunner;
-
import java.util.HashMap;
-
import java.util.Map;
-
-
-
-
public class UserMapperTest {
-
-
-
private UserMapper userMapper;
-
-
-
public void testDelete(){
-
-
//用法一:
-
// QueryWrapper<User> wrapper = new QueryWrapper<>();
-
// wrapper.eq("user_name", "caocao1")
-
// .eq("password", "123456");
-
-
//用法二(推荐使用):
-
User user = new User();
-
user.setPassword("123456");
-
user.setUserName("caocao");
-
-
QueryWrapper<User> wrapper = new QueryWrapper<>(user);
-
-
// 根据包装条件做删除
-
int result = this.userMapper.delete(wrapper);
-
System.out.println("result => " result);
-
}
4.查询操作
MP提供了多种查询操作,包括根据id查询、批量查询、查询单条数据、查询列表、分页查询等操作。
①通过id查询---selectById
方法定义:
/** * 根据 ID 查询 * * @param id 主键ID */ T selectById(Serializable id);映射出来的SQL语句:
SELECT id,user_name,password,name,age,email FROM tb_user WHERE id=?
-
import cn.itcast.mp.mapper.UserMapper;
-
import cn.itcast.mp.pojo.User;
-
import org.junit.Test;
-
import org.junit.runner.RunWith;
-
import org.springframework.beans.factory.annotation.Autowired;
-
import org.springframework.boot.test.context.SpringBootTest;
-
import org.springframework.test.context.junit4.SpringRunner;
-
-
-
-
public class UserMapperTest {
-
-
-
private UserMapper userMapper;
-
-
-
public void testSelectById() {
-
-
//根据id查询数据
-
User user = this.userMapper.selectById(2L);
-
System.out.println("result = " user);
-
}
-
}
-
②根据id批量查询数据----selectBatchIds()
方法定义:
/** * 查询(根据ID 批量查询) * * @param idList 主键ID列表(不能为 null 以及 empty) */ List<T> selectBatchIds( Collection<? extends Serializable> idList);映射出来的SQL语句:
SELECT id,user_name,password,name,age,email FROM tb_user WHERE id IN ( ? , ? , ? )
-
import cn.itcast.mp.mapper.UserMapper;
-
import cn.itcast.mp.pojo.User;
-
import org.junit.Test;
-
import org.junit.runner.RunWith;
-
import org.springframework.beans.factory.annotation.Autowired;
-
import org.springframework.boot.test.context.SpringBootTest;
-
import org.springframework.test.context.junit4.SpringRunner;
-
import java.util.Arrays;
-
import java.util.List;
-
-
-
-
public class UserMapperTest {
-
-
-
private UserMapper userMapper;
-
-
-
public void testSelectBatchIds(){
-
// 根据id批量查询数据
-
List<User> users = this.userMapper.selectBatchIds(Arrays.asList(2L, 3L, 4L, 100L));
-
for (User user : users) {
-
System.out.println(user);
-
}
-
}
-
}
③根据查询条件查询并返回一条数据(查询结果只有一条数据,若查出多条则报错)----selectOne()
方法定义:
/** * 根据 entity 条件,查询一条记录 * * @param queryWrapper 实体对象封装操作类(可以为 null) */ T selectOne(; Wrapper<T> queryWrapper)映射出来的SQL语句:
SELECT id,user_name,password,name,age,email FROM tb_user WHERE name = ?
-
import cn.itcast.mp.mapper.UserMapper;
-
import cn.itcast.mp.pojo.User;
-
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
-
import org.junit.Test;
-
import org.junit.runner.RunWith;
-
import org.springframework.beans.factory.annotation.Autowired;
-
import org.springframework.boot.test.context.SpringBootTest;
-
import org.springframework.test.context.junit4.SpringRunner;
-
-
-
-
public class UserMapperTest {
-
-
-
private UserMapper userMapper;
-
-
-
public void testSelectOne(){
-
QueryWrapper<User> wrapper = new QueryWrapper<>();
-
//查询条件
-
wrapper.eq("password", "123456");
-
// 查询的数据超过一条时,会抛出异常
-
User user = this.userMapper.selectOne(wrapper);
-
System.out.println(user);
-
}
-
}
④根据条件查询数据的总数据条数----selectCount()
方法定义:
/** * 根据 Wrapper 条件,查询总记录数 * * @param queryWrapper 实体对象封装操作类(可以为 null) */ Integer selectCount(; Wrapper<T> queryWrapper)映射出来的SQL语句:
SELECT COUNT( 1 ) FROM tb_user WHERE age > ?
-
import cn.itcast.mp.mapper.UserMapper;
-
import cn.itcast.mp.pojo.User;
-
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
-
import org.junit.Test;
-
import org.junit.runner.RunWith;
-
import org.springframework.beans.factory.annotation.Autowired;
-
import org.springframework.boot.test.context.SpringBootTest;
-
import org.springframework.test.context.junit4.SpringRunner;
-
-
-
-
public class UserMapperTest {
-
-
-
private UserMapper userMapper;
-
-
-
-
public void testSelectCount(){
-
-
QueryWrapper<User> wrapper = new QueryWrapper<>();
-
wrapper.gt("age", 20); // 条件:年龄大于20岁的用户
-
-
// 根据条件查询数据条数
-
Integer count = this.userMapper.selectCount(wrapper);
-
System.out.println("count => " count);
-
}
-
}
⑤根据条件查询并返回全部记录列表----selectList()
方法定义:
/** * 根据 entity 条件,查询全部记录 * * @param queryWrapper 实体对象封装操作类(可以为 null) */ List<T> selectList(; Wrapper<T> queryWrapper)映射出来的SQL语句:
SELECT id,user_name,password,name,age,email FROM tb_user WHERE age > ?
-
import cn.itcast.mp.mapper.UserMapper;
-
import cn.itcast.mp.pojo.User;
-
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
-
import org.junit.Test;
-
import org.junit.runner.RunWith;
-
import org.springframework.beans.factory.annotation.Autowired;
-
import org.springframework.boot.test.context.SpringBootTest;
-
import org.springframework.test.context.junit4.SpringRunner;
-
import java.util.List;
-
-
-
public class UserMapperTest {
-
-
-
private UserMapper userMapper;
-
-
-
-
public void testSelectList(){
-
QueryWrapper<User> wrapper = new QueryWrapper<>();
-
//设置查询条件
-
wrapper.like("email", "itcast");
-
-
List<User> users = this.userMapper.selectList(wrapper);
-
for (User user : users) {
-
System.out.println(user);
-
}
-
}
-
}
⑥根据条件查询并返回全部数据(并且翻页)----selectPage()
方法定义:
/** * 根据 entity 条件,查询全部记录(并翻页) * * @param page 分页查询条件(可以为 RowBounds.DEFAULT) * @param queryWrapper 实体对象封装操作类(可以为 null) */ IPage<T> selectPage(IPage<T> page, ; Wrapper<T> queryWrapper)映射出来的SQL语句:
SELECT COUNT(1) FROM tb_user WHERE age > ?
SELECT id,user_name,password,name,age,email FROM tb_user WHERE age > ? LIMIT ?,?
配置分页插件:
-
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;
-
-
-
//设置mapper接口的扫描包
-
public class MybatisPlusConfig {
-
-
/**
-
* 分页插件
-
*/
-
-
public PaginationInterceptor paginationInterceptor() {
-
-
return new PaginationInterceptor();
-
}
-
}
-
-
import cn.itcast.mp.mapper.UserMapper;
-
import cn.itcast.mp.pojo.User;
-
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
-
import com.baomidou.mybatisplus.core.metadata.IPage;
-
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-
import org.junit.Test;
-
import org.junit.runner.RunWith;
-
import org.springframework.beans.factory.annotation.Autowired;
-
import org.springframework.boot.test.context.SpringBootTest;
-
import org.springframework.test.context.junit4.SpringRunner;
-
import java.util.List;
-
-
-
-
public class UserMapperTest {
-
-
-
private UserMapper userMapper;
-
-
-
// 测试分页查询
-
-
public void testSelectPage(){
-
-
Page<User> page = new Page<>(3,1); //查询第一页,查询1条数据
-
-
QueryWrapper<User> wrapper = new QueryWrapper<>();
-
//设置查询条件
-
wrapper.like("email", "itcast");
-
-
IPage<User> iPage = this.userMapper.selectPage(page, wrapper);
-
System.out.println("数据总条数: " iPage.getTotal());
-
System.out.println("数据总页数: " iPage.getPages());
-
System.out.println("当前页数: " iPage.getCurrent());
-
-
List<User> records = iPage.getRecords();
-
for (User record : records) {
-
System.out.println(record);
-
}
-
-
}
五、SQL注入的原理
在MP中,ISqlInjector负责SQL的注入工作,它是一个接口,AbstractSqlInjector是它的实现类,实现关系如下:
在AbstractSqlInjector中,主要是由inspectInject()方法进行注入的,如下:
public void inspectInject(MapperBuilderAssistant builderAssistant, Class<?> mapperClass) { Class<?> modelClass = extractModelClass(mapperClass); if (modelClass != null) { String className = mapperClass.toString(); Set<String> mapperRegistryCache = GlobalConfigUtils.getMapperRegistryCache(builderAssistant.getConfiguration()); if (!mapperRegistryCache.contains(className)) { List<AbstractMethod> methodList = this.getMethodList(); if (CollectionUtils.isNotEmpty(methodList)) { TableInfo tableInfo = TableInfoHelper.initTableInfo(builderAssistant, modelClass); // 循环注入自定义方法 methodList.forEach(m -> m.inject(builderAssistant, mapperClass,modelClass, tableInfo)); } else { logger.debug(mapperClass.toString() ", No effective injection method was found."); } mapperRegistryCache.add(className); } } }在实现方法中, methodList.forEach(m -> m.inject(builderAssistant, mapperClass, modelClass, tableInfo)); 是关键,循环遍历方法,进行注入。
最终调用抽象方法injectMappedStatement进行真正的注入:
/** * 注入自定义 MappedStatement * * @param mapperClass mapper 接口 * @param modelClass mapper 泛型 * @param tableInfo 数据库表反射信息 * @return MappedStatement */ public abstract MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo);查看该方法的实现:
以SelectById为例查看:
public class SelectById extends AbstractMethod { public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) { SqlMethod sqlMethod = SqlMethod.LOGIC_SELECT_BY_ID; SqlSource sqlSource = new RawSqlSource(configuration, String.format(sqlMethod.getSql(), sqlSelectColumns(tableInfo, false), tableInfo.getTableName(), tableInfo.getKeyColumn(),tableInfo.getKeyProperty(), tableInfo.getLogicDeleteSql(true, false)), Object.class); return this.addSelectMappedStatement(mapperClass, sqlMethod.getMethod(),sqlSource, modelClass, tableInfo); } }可以看到,生成了SqlSource对象,再将SQL通过addSelectMappedStatement方法添加到meppedStatements中。
六、配置
1)基本配置
1.configLocation----声名配置文件的位置
MyBatis 配置文件位置,如果您有单独的 MyBatis 配置,请将其路径配置到 configLocation 中。 MyBatis Configuration 的具体内容请参考MyBatis 官方文档。
Spring Boot:
mybatis-plus.config-location = classpath:mybatis-config.xml
Spring MVC:
-
<bean id="sqlSessionFactory" class="com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean">
-
<property name="configLocation" value="classpath:mybatis-config.xml"/>
-
</bean>
2.mapperLocations----配置自定义方法的位置
MyBatis Mapper 所对应的 XML 文件位置,如果您在 Mapper 中有自定义方法(XML 中有自定义实现),需要进行 该配置,告诉 Mapper 所对应的 XML 文件位置。
Spring Boot:
mybatis-plus.mapper-locations = classpath*:mybatis/*.xml
Maven 多模块项目的扫描路径需以 classpath*: 开头 (即加载多个 jar 包下的 XML 文件)
Spring MVC:
-
<bean id="sqlSessionFactory"
-
class="com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean">
-
<property name="mapperLocations" value="classpath*:mybatis/*.xml"/>
-
</bean>
3.typeAliasesPackage---配置别名包扫描路径,配置后可直接用类名
MyBaits 别名包扫描路径,通过该属性可以给包中的类注册别名,注册后在 Mapper 对应的 XML 文件中可以直接使 用类名,而不用使用全限定的类名(即 XML 中调用的时候不用包含包名)。
Spring Boot:
mybatis-plus.type-aliases-package = cn.itcast.mp.pojo
Spring MVC:
-
<bean id="sqlSessionFactory"
-
class="com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean">
-
<property name="typeAliasesPackage" value="com.baomidou.mybatisplus.samples.quickstart.entity"/>
-
</bean>
2)进阶配置
本部分(Configuration)的配置大都为 MyBatis 原生支持的配置,这意味着您可以通过 MyBatis XML 配置文件的形 式进行配置。
1.mapUnderscoreToCamelCase----配置是否开启自动驼峰命名规则映射
- 类型: boolean
- 默认值: true
是否开启自动驼峰命名规则(camel case)映射,即从经典数据库列名 A_COLUMN(下划线命名) 到经典 Java 属 性名 aColumn(驼峰命名) 的类似映射。
注意: 此属性在 MyBatis 中原默认值为 false,在 MyBatis-Plus 中,此属性也将用于生成最终的 SQL 的 select body 如果您的数据库命名符合规则无需使用 @TableField 注解指定数据库字段名。
SpringBoot:
-
#关闭自动驼峰映射,该参数不能和mybatis-plus.config-location同时存在
-
mybatis-plus.configuration.map-underscore-to-camel-case=false
2.cacheEnabled---配置是否需要缓存
- 类型: boolean
- 默认值: true
全局地开启或关闭配置文件中的所有映射器已经配置的任何缓存,默认为 true。
SpringBoot:
mybatis-plus.configuration.cache-enabled=false
3)DB 策略配置
1.idType---配置主键类型
- 类型: com.baomidou.mybatisplus.annotation.IdType
- 默认值: ID_WORKER
全局默认主键类型,设置后,即可省略实体对象中的@TableId(type = IdType.AUTO)配置。
SpringBoot:
mybatis-plus.global-config.db-config.id-type=auto
SpringMVC:
-
<!--这里使用MP提供的sqlSessionFactory,完成了Spring与MP的整合-->
-
<bean id="sqlSessionFactory"
-
class="com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean">
-
<property name="dataSource" ref="dataSource"/>
-
<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>
3.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="dataSource" ref="dataSource"/>
-
<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"/>
-
<property name="tablePrefix" value="tb_"/>
-
</bean>
-
</property>
-
</bean>
-
</property>
-
</bean>
七、条件构造器
在MP中,Wrapper接口的实现类关系如下:
说明: QueryWrapper(LambdaQueryWrapper) 和 UpdateWrapper(LambdaUpdateWrapper) 的父类 用于生成 sql 的 where 条件, entity 属性也用于生成 sql 的 where 条件 注意: entity 生成的 where 条件与 使用各个 api 生成 的 where 条件没有任何关联行为。
一)allEq
①说明
- allEq(Map params)
- allEq(Map params, boolean null2IsNull)
- allEq(boolean condition, Map params, boolean null2IsNull)
个别参数说明: params : key 为数据库字段名, value 为字段值 null2IsNull : 为 true 则在 map 的 value 为 null 时调用 isNull 方法,为 false 时则忽略 value 为 null 的
- 例1: allEq({id:1,name:"老王",age:null}) ---> id = 1 and name = '老王' and age is null
- 例2: allEq({id:1,name:"老王",age:null}, false) ---> id = 1 and name = '老王'
- allEq(BiPredicate filter, Map params)
- allEq(BiPredicate filter, Map params, boolean null2IsNull)
- allEq(boolean condition, BiPredicate filter, Map params, boolean null2IsNull)
个别参数说明: filter : 过滤函数,是否允许字段传入比对条件中 params 与 null2IsNull : 同上
例1: allEq((k,v) -> k.indexOf("a") > 0, {id:1,name:"老王",age:null}) ---> name = '老王' and age is null
例2: allEq((k,v) -> k.indexOf("a") > 0, {id:1,name:"老王",age:null}, false) ---> name = '老王'
测试:
-
import cn.itcast.mp.mapper.UserMapper;
-
import cn.itcast.mp.pojo.User;
-
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
-
import org.junit.Test;
-
import org.junit.runner.RunWith;
-
import org.springframework.beans.factory.annotation.Autowired;
-
import org.springframework.boot.test.context.SpringBootTest;
-
import org.springframework.test.context.junit4.SpringRunner;
-
import java.util.HashMap;
-
import java.util.List;
-
import java.util.Map;
-
-
-
-
public class UserMapperTest {
-
-
-
private UserMapper userMapper;
-
-
-
public void testWrapper() {
-
QueryWrapper<User> wrapper = new QueryWrapper<>();
-
-
//设置条件
-
Map<String,Object> params = new HashMap<>();
-
params.put("name", "曹操");
-
params.put("age", "20");
-
params.put("password", null);
-
-
// wrapper.allEq(params);//SELECT * FROM tb_user WHERE password IS NULL AND name = ? AND age = ?
-
-
// wrapper.allEq(params,false); //SELECT * FROM tb_user WHERE name = ? AND age = ?
-
-
// wrapper.allEq((k, v) -> (k.equals("name") || k.equals("age")) ,params);//SELECT * FROM tb_user WHERE name = ? AND age = ?
-
-
List<User> users = this.userMapper.selectList(wrapper);
-
for (User user : users) {
-
System.out.println(user);
-
}
-
}
-
}
-
二)基本比较操作
- 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, ...)
-
import cn.itcast.mp.mapper.UserMapper;
-
import cn.itcast.mp.pojo.User;
-
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
-
import org.junit.Test;
-
import org.junit.runner.RunWith;
-
import org.springframework.beans.factory.annotation.Autowired;
-
import org.springframework.boot.test.context.SpringBootTest;
-
import org.springframework.test.context.junit4.SpringRunner;
-
import java.util.List;
-
-
-
-
public class UserMapperTest {
-
-
-
private UserMapper userMapper;
-
-
-
public void testEq() {
-
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", "123456").ge("age", 20).in("name", "李四", "王五", "赵六");
-
-
List<User> users = this.userMapper.selectList(wrapper);
-
for (User user : users) {
-
System.out.println(user);
-
}
-
}
-
}
三)模糊查询
- 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 '王%'
-
import cn.itcast.mp.mapper.UserMapper;
-
import cn.itcast.mp.pojo.User;
-
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
-
import org.junit.Test;
-
import org.junit.runner.RunWith;
-
import org.springframework.beans.factory.annotation.Autowired;
-
import org.springframework.boot.test.context.SpringBootTest;
-
import org.springframework.test.context.junit4.SpringRunner;
-
import java.util.List;
-
-
-
-
public class UserMapperTest {
-
-
-
private UserMapper userMapper;
-
-
-
public void testWrapper() {
-
-
QueryWrapper<User> wrapper = new QueryWrapper<>();
-
-
//SELECT id,user_name,password,name,age,email FROM tb_user WHERE name LIKE ?
-
//Parameters: %曹%(String)
-
-
wrapper.like("name", "曹");
-
-
List<User> users = this.userMapper.selectList(wrapper);
-
for (User user : users) {
-
System.out.println(user);
-
}
-
}
-
}
四)排序
- 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
-
import cn.itcast.mp.mapper.UserMapper;
-
import cn.itcast.mp.pojo.User;
-
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
-
import org.junit.Test;
-
import org.junit.runner.RunWith;
-
import org.springframework.beans.factory.annotation.Autowired;
-
import org.springframework.boot.test.context.SpringBootTest;
-
import org.springframework.test.context.junit4.SpringRunner;
-
import java.util.List;
-
-
-
-
public class UserMapperTest {
-
-
-
private UserMapper userMapper;
-
-
-
public void testWrapper() {
-
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> users = this.userMapper.selectList(wrapper);
-
for (User user : users) {
-
System.out.println(user);
-
}
-
}
-
}
五)逻辑查询
- or
- 拼接 OR
- 主动调用 or 表示紧接着下一个方法不是用 and 连接!(不调用 or 则默认为使用 and 连接)
- and
- AND 嵌套
- 例: and(i -> i.eq("name", "李白").ne("status", "活着")) ---> and (name = '李白' and status <> '活着')
-
import cn.itcast.mp.mapper.UserMapper;
-
import cn.itcast.mp.pojo.User;
-
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
-
import org.junit.Test;
-
import org.junit.runner.RunWith;
-
import org.springframework.beans.factory.annotation.Autowired;
-
import org.springframework.boot.test.context.SpringBootTest;
-
import org.springframework.test.context.junit4.SpringRunner;
-
import java.util.List;
-
-
-
-
public class UserMapperTest {
-
-
-
private UserMapper userMapper;
-
-
-
public void testWrapper() {
-
-
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", 24);
-
-
List<User> users = this.userMapper.selectList(wrapper);
-
for (User user : users) {
-
System.out.println(user);
-
}
-
}
-
}
六)select
在MP查询中,默认查询所有的字段,如果有需要也可以通过select方法进行指定字段。
-
import cn.itcast.mp.mapper.UserMapper;
-
import cn.itcast.mp.pojo.User;
-
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
-
import org.junit.Test;
-
import org.junit.runner.RunWith;
-
import org.springframework.beans.factory.annotation.Autowired;
-
import org.springframework.boot.test.context.SpringBootTest;
-
import org.springframework.test.context.junit4.SpringRunner;
-
-
import java.util.List;
-
-
-
-
public class UserMapperTest {
-
-
-
private UserMapper userMapper;
-
-
-
public void testWrapper() {
-
QueryWrapper<User> wrapper = new QueryWrapper<>();
-
-
//SELECT id,name,age FROM tb_user WHERE name = ? OR age = ?
-
-
wrapper.eq("name", "李四").or().eq("age", 24).select("id", "name", "age");
-
-
List<User> users = this.userMapper.selectList(wrapper);
-
for (User user : users) {
-
System.out.println(user);
-
}
-
}
-
}
八、ActiveRecord
ActiveRecord也属于ORM(对象关系映射)层,由Rails最早提出,遵循标准的ORM模型:表映射到记录,记 录映射到对象,字段映射到对象属性。配合遵循的命名和配置惯例,能够很大程度的快速实现模型的操作,而 且简洁易懂。
ActiveRecord的主要思想是:
- 每一个数据库表对应创建一个类,类的每一个对象实例对应于数据库中表的一行记录;通常表的每个字段 在类中都有相应的Field;
- ActiveRecord同时负责把自己持久化,在ActiveRecord中封装了对数据库的访问,即CURD;;
- ActiveRecord是一种领域模型(Domain Model),封装了部分业务逻辑;
一)开启AR之旅
在MP中,开启AR非常简单,只需要将实体对象继承Model即可。
-
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;
-
-
-
-
-
public class User extends Model<User> {
-
private Long id;
-
private String userName;
-
private String password;
-
private String name;
-
private Integer age;
-
private String email;
-
}
九、Mybatis-Plus的插件
一)mybatis的插件机制
MyBatis 允许你在已映射语句执行过程中的某一点进行拦截调用。默认情况下,MyBatis 允许使用插件来拦截的方法 调用包括:
1. Executor (update, query, flushStatements, commit, rollback, getTransaction, close, isClosed) 拦截执行器的方法
2. ParameterHandler (getParameterObject, setParameters) 拦截参数的处理
3. ResultSetHandler (handleResultSets, handleOutputParameters) 拦截结果集的处理
4. StatementHandler (prepare, parameterize, batch, update, query) 拦截Sql语法构建的处理
我们看到了可以拦截Executor接口的部分方法,比如update,query,commit,rollback等方法,还有其他接口的 一些方法等。
总体概括为:
1. 拦截执行器的方法
2. 拦截参数的处理
3. 拦截结果集的处理
4. 拦截Sql语法构建的处理
拦截器示例:
-
package cn.itcast.mp.plugins;
-
-
import org.apache.ibatis.executor.Executor;
-
import org.apache.ibatis.mapping.MappedStatement;
-
import org.apache.ibatis.plugin.*;
-
-
import java.util.Properties;
-
-
-
-
-
-
public class MyInterceptor implements Interceptor {
-
-
-
public Object intercept(Invocation invocation) throws Throwable {
-
//拦截方法,具体业务逻辑编写的位置
-
return invocation.proceed();
-
}
-
-
-
public Object plugin(Object target) {
-
//创建target对象的代理对象,目的是将当前拦截器加入到该对象中
-
return Plugin.wrap(target, this);
-
}
-
-
-
public void setProperties(Properties properties) {
-
//属性设置
-
}
-
}
注入到Spring容器:
-
/**
-
* 自定义拦截器
-
*/
-
-
public MyInterceptor myInterceptor(){
-
return new MyInterceptor();
-
}
二)执行分析插件
在MP中提供了对SQL执行的分析的插件,可用作阻断全表更新、删除的操作,
注意:该插件仅适用于开发环境,不 适用于生产环境。
SpringBoot配置:
-
-
public SqlExplainInterceptor sqlExplainInterceptor(){
-
-
SqlExplainInterceptor sqlExplainInterceptor = new SqlExplainInterceptor();
-
-
List<ISqlParser> sqlParserList = new ArrayList<>();
-
-
// 攻击 SQL 阻断解析器、加入解析链
-
sqlParserList.add(new BlockAttackSqlParser());
-
sqlExplainInterceptor.setSqlParserList(sqlParserList);
-
-
return sqlExplainInterceptor;
-
}
三)性能分析插件
性能分析拦截器,用于输出每条 SQL 语句及其执行时间,可以设置最大执行时间,超过时间会抛出异常。
该插件只用于开发环境,不建议生产环境使用。
配置:
-
<configuration>
-
<plugins>
-
<!-- 性能分析插件 -->
-
<!-- SQL 执行性能分析,开发环境使用,线上不推荐。 maxTime 指的是 sql 最大执行时长 -->
-
<plugin interceptor="com.baomidou.mybatisplus.extension.plugins.PerformanceInterceptor">
-
<!--最大的执行时间,单位为毫秒-->
-
<property name="maxTime" value="100"/>
-
<!--对输出的SQL做格式化,默认为false-->
-
<property name="format" value="true"/>
-
</plugin>
-
</configuration>
四)乐观锁插件
1.主要适用场景
意图: 当要更新一条记录的时候,希望这条记录没有被别人更新
乐观锁实现方式:
- 取出记录时,获取当前version
- 更新时,带上这个version
- 执行更新时, set version = newVersion where version = oldVersion
- 如果version不对,就更新失败
插件配置:
①spring xml:
<bean class="com.baomidou.mybatisplus.extension.plugins.OptimisticLockerInterceptor"/>
②spring boot:
-
-
public OptimisticLockerInterceptor optimisticLockerInterceptor() {
-
return new OptimisticLockerInterceptor();
-
}
使用步骤:
需要为实体字段添加@Version注解。
第一步,为表添加version字段,并且设置初始值为1:
-
ALTER TABLE `tb_user`
-
ADD COLUMN `version` int(10) NULL AFTER `email`;
-
-
UPDATE `tb_user` SET `version`='1';
第二步,为User实体对象添加version字段,并且添加@Version注解:
-
-
private Integer version;
测试:
-
-
public void testUpdateVersion(){
-
User user = new User();
-
user.setId(2L);// 查询条件
-
-
User userVersion = user.selectById();
-
-
user.setAge(23); // 更新的数据
-
user.setVersion(userVersion.getVersion()); // 当前的版本信息
-
-
boolean result = user.updateById();
-
System.out.println("result => " result);
-
}
特别说明:
- 支持的数据类型只有:int,Integer,long,Long,Date,Timestamp,LocalDateTime
- 整数类型下 newVersion = oldVersion 1
- newVersion 会回写到 entity 中
- 仅支持 updateById(id) 与 update(entity, wrapper) 方法
- 在 update(entity, wrapper) 方法下, wrapper 不能复用!!!
十、Sql 注入器实现自定义全局操作
当我们需要扩充BaseMapper中的方法,就需要用到Sql 注入器
①编写MyBaseMapper(其他的Mapper都可以继承该Mapper,这样实现了统一的扩展)
-
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
-
import java.util.List;
-
-
public interface MyBaseMapper<T> extends BaseMapper<T> {
-
List<T> findAll();
-
-
// 扩展其他的方法
-
}
注意:其他mapper都应该继承MyBaseMapper,而MyBaseMapper应该继承BaseMapper
如:
-
package cn.itcast.mp.mapper;
-
-
import cn.itcast.mp.pojo.User;
-
-
public interface UserMapper extends MyBaseMapper<User> {
-
-
User findById(Long id);
-
}
② 编写MySqlInjector
如果直接继承AbstractSqlInjector的话,原有的BaseMapper中的方法将失效,所以我们选择继承DefaultSqlInjector 进行扩展。
-
package cn.itcast.mp.injectors;
-
-
import com.baomidou.mybatisplus.core.injector.AbstractMethod;
-
import com.baomidou.mybatisplus.core.injector.DefaultSqlInjector;
-
-
import java.util.ArrayList;
-
import java.util.List;
-
-
public class MySqlInjector extends DefaultSqlInjector {
-
-
-
public List<AbstractMethod> getMethodList() {
-
List<AbstractMethod> list = new ArrayList<>();
-
-
// 获取父类中的集合
-
list.addAll(super.getMethodList());
-
-
// 再扩充自定义的方法
-
list.add(new FindAll());
-
-
return list;
-
}
-
}
③编写FindAll
-
package cn.itcast.mp.injectors;
-
-
import com.baomidou.mybatisplus.core.injector.AbstractMethod;
-
import com.baomidou.mybatisplus.core.metadata.TableInfo;
-
import org.apache.ibatis.mapping.MappedStatement;
-
import org.apache.ibatis.mapping.SqlSource;
-
-
public class FindAll extends AbstractMethod {
-
-
-
public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
-
-
String sql = "select * from " tableInfo.getTableName();
-
SqlSource sqlSource = languageDriver.createSqlSource(configuration,sql, modelClass);
-
-
return this.addSelectMappedStatement(mapperClass, "findAll", sqlSource, modelClass, tableInfo);
-
}
-
}
④注册到Spring容器
-
/**
-
* 注入自定义的SQL注入器
-
* @return
-
*/
-
-
public MySqlInjector mySqlInjector(){
-
return new MySqlInjector();
-
}
十一、自动填充功能
有些时候我们可能会有这样的需求,插入或者更新数据时,希望有些字段可以自动填充数据,比如密码、version 等。在MP中提供了这样的功能,可以实现自动填充。
开发步骤:
①添加@TableField注解
-
//插入数据时进行填充
-
private String password;
FieldFill提供了多种模式选择:
-
public enum FieldFill {
-
/**
-
* 默认不处理
-
*/
-
DEFAULT,
-
/**
-
* 插入时填充字段
-
*/
-
INSERT,
-
/**
-
* 更新时填充字段
-
*/
-
UPDATE,
-
/**
-
* 插入和更新时填充字段
-
*/
-
INSERT_UPDATE
-
}
② 编写MyMetaObjectHandler
-
package cn.itcast.mp.handler;
-
-
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
-
import org.apache.ibatis.reflection.MetaObject;
-
import org.springframework.stereotype.Component;
-
-
-
public class MyMetaObjectHandler implements MetaObjectHandler {
-
-
/**
-
* 插入数据时填充
-
* @param metaObject
-
*/
-
-
public void insertFill(MetaObject metaObject) {
-
// 先获取到password的值,再进行判断,如果为空,就进行填充,如果不为空,就不做处理
-
Object password = getFieldValByName("password", metaObject);
-
//字段为空就填入
-
if(null == password){
-
setFieldValByName("password", "888888", metaObject);
-
}
-
}
-
-
/**
-
* 更新数据时填充
-
* @param metaObject
-
*/
-
-
public void updateFill(MetaObject metaObject) {
-
-
}
-
}
十二、逻辑删除
开发系统时,有时候在实现功能时,删除操作需要实现逻辑删除,所谓逻辑删除就是将数据标记为删除,而并非真正的物理删除(非DELETE操作),查询时需要携带状态条件,确保被标记的数据不被查询到。这样做的目的就是避免数据被真正的删除。
开发步骤:
①修改表结构
为tb_user表增加deleted字段,用于表示数据是否被删除,1代表删除,0代表未删除。
-
ALTER TABLE `tb_user`
-
ADD COLUMN `deleted` int(1) NULL DEFAULT 0 COMMENT '1代表删除,0代表未删除' AFTER
-
`version`;
同时,也修改User实体,增加deleted属性并且添加@TableLogic注解:
-
-
private Integer deleted;
②配置
application.properties:
-
# 逻辑已删除值(默认为 1)
-
mybatis-plus.global-config.db-config.logic-delete-value=1
-
# 逻辑未删除值(默认为 0)
-
mybatis-plus.global-config.db-config.logic-not-delete-value=0
十三、通用枚举
解决了繁琐的配置,让 mybatis 优雅的使用枚举属性!
开发步骤:
①修改表结构
-
ALTER TABLE `tb_user`
-
ADD COLUMN `sex` int(1) NULL DEFAULT 1 COMMENT '1-男,2-女' AFTER `deleted`;
②定义枚举
-
package cn.itcast.mp.enums;
-
-
import com.baomidou.mybatisplus.core.enums.IEnum;
-
-
public enum SexEnum implements IEnum<Integer> {
-
-
MAN(1,"男"),
-
WOMAN(2,"女");
-
-
private int value;
-
private String desc;
-
-
SexEnum(int value, String desc) {
-
this.value = value;
-
this.desc = desc;
-
}
-
-
-
public Integer getValue() {
-
return this.value;
-
}
-
-
-
public String toString() {
-
return this.desc;
-
}
-
}
③配置
-
-
mybatis-plus.type-enums-package=cn.itcast.mp.enums
④修改实体
private SexEnum sex;
十四、代码生成器
AutoGenerator 是 MyBatis-Plus 的代码生成器,通过 AutoGenerator 可以快速生成 Entity、Mapper、Mapper XML、Service、Controller 等各个模块的代码,极大的提升了开发效率。
开发步骤:
①创建工程导入包
-
-
<project xmlns="http://maven.apache.org/POM/4.0.0"
-
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-
<modelVersion>4.0.0</modelVersion>
-
-
<parent>
-
<groupId>org.springframework.boot</groupId>
-
<artifactId>spring-boot-starter-parent</artifactId>
-
<version>2.1.4.RELEASE</version>
-
</parent>
-
-
<groupId>cn.itcast.mp</groupId>
-
<artifactId>itcast-mp-generator</artifactId>
-
<version>1.0-SNAPSHOT</version>
-
-
<dependencies>
-
<dependency>
-
<groupId>org.springframework.boot</groupId>
-
<artifactId>spring-boot-starter-test</artifactId>
-
<scope>test</scope>
-
</dependency>
-
-
<!--mybatis-plus的springboot支持-->
-
<dependency>
-
<groupId>com.baomidou</groupId>
-
<artifactId>mybatis-plus-boot-starter</artifactId>
-
<version>3.1.1</version>
-
</dependency>
-
<dependency>
-
<groupId>com.baomidou</groupId>
-
<artifactId>mybatis-plus-generator</artifactId>
-
<version>3.1.1</version>
-
</dependency>
-
<dependency>
-
<groupId>org.springframework.boot</groupId>
-
<artifactId>spring-boot-starter-freemarker</artifactId>
-
</dependency>
-
<!--mysql驱动-->
-
<dependency>
-
<groupId>mysql</groupId>
-
<artifactId>mysql-connector-java</artifactId>
-
<version>5.1.47</version>
-
</dependency>
-
<dependency>
-
<groupId>org.slf4j</groupId>
-
<artifactId>slf4j-log4j12</artifactId>
-
</dependency>
-
-
</dependencies>
-
-
<build>
-
<plugins>
-
<plugin>
-
<groupId>org.springframework.boot</groupId>
-
<artifactId>spring-boot-maven-plugin</artifactId>
-
</plugin>
-
</plugins>
-
</build>
-
-
</project>
②写入代码(一般直接套用)
-
package cn.itcast.mp.generator;
-
-
import java.util.ArrayList;
-
import java.util.List;
-
import java.util.Scanner;
-
-
import com.baomidou.mybatisplus.core.exceptions.MybatisPlusException;
-
import com.baomidou.mybatisplus.core.toolkit.StringPool;
-
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
-
import com.baomidou.mybatisplus.generator.AutoGenerator;
-
import com.baomidou.mybatisplus.generator.InjectionConfig;
-
import com.baomidou.mybatisplus.generator.config.DataSourceConfig;
-
import com.baomidou.mybatisplus.generator.config.FileOutConfig;
-
import com.baomidou.mybatisplus.generator.config.GlobalConfig;
-
import com.baomidou.mybatisplus.generator.config.PackageConfig;
-
import com.baomidou.mybatisplus.generator.config.StrategyConfig;
-
import com.baomidou.mybatisplus.generator.config.TemplateConfig;
-
import com.baomidou.mybatisplus.generator.config.po.TableInfo;
-
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
-
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;
-
-
/**
-
* <p>
-
* mysql 代码生成器演示例子
-
* </p>
-
*/
-
public class MysqlGenerator {
-
-
/**
-
* <p>
-
* 读取控制台内容
-
* </p>
-
*/
-
public static String scanner(String tip) {
-
Scanner scanner = new Scanner(System.in);
-
StringBuilder help = new StringBuilder();
-
help.append("请输入" tip ":");
-
System.out.println(help.toString());
-
if (scanner.hasNext()) {
-
String ipt = scanner.next();
-
if (StringUtils.isNotEmpty(ipt)) {
-
return ipt;
-
}
-
}
-
throw new MybatisPlusException("请输入正确的" tip "!");
-
}
-
-
/**
-
* RUN THIS
-
*/
-
public static void main(String[] args) {
-
// 代码生成器
-
AutoGenerator mpg = new AutoGenerator();
-
-
// 全局配置
-
GlobalConfig gc = new GlobalConfig();
-
String projectPath = System.getProperty("user.dir");
-
gc.setOutputDir(projectPath "/src/main/java");
-
gc.setAuthor("itcast");
-
gc.setOpen(false);
-
mpg.setGlobalConfig(gc);
-
-
// 数据源配置
-
DataSourceConfig dsc = new DataSourceConfig();
-
dsc.setUrl("jdbc:mysql://127.0.0.1:3306/mp?useUnicode=true&useSSL=false&characterEncoding=utf8");
-
// dsc.setSchemaName("public");
-
dsc.setDriverName("com.mysql.jdbc.Driver");
-
dsc.setUsername("root");
-
dsc.setPassword("root");
-
mpg.setDataSource(dsc);
-
-
// 包配置
-
PackageConfig pc = new PackageConfig();
-
pc.setModuleName(scanner("模块名"));
-
pc.setParent("cn.itcast.mp.generator");
-
mpg.setPackageInfo(pc);
-
-
// 自定义配置
-
InjectionConfig cfg = new InjectionConfig() {
-
-
public void initMap() {
-
// to do nothing
-
}
-
};
-
List<FileOutConfig> focList = new ArrayList<>();
-
focList.add(new FileOutConfig("/templates/mapper.xml.ftl") {
-
-
public String outputFile(TableInfo tableInfo) {
-
// 自定义输入文件名称
-
return projectPath "/itcast-mp-generator/src/main/resources/mapper/" pc.getModuleName()
-
"/" tableInfo.getEntityName() "Mapper" StringPool.DOT_XML;
-
}
-
});
-
cfg.setFileOutConfigList(focList);
-
mpg.setCfg(cfg);
-
mpg.setTemplate(new TemplateConfig().setXml(null));
-
-
// 策略配置
-
StrategyConfig strategy = new StrategyConfig();
-
strategy.setNaming(NamingStrategy.underline_to_camel);
-
strategy.setColumnNaming(NamingStrategy.underline_to_camel);
-
// strategy.setSuperEntityClass("com.baomidou.mybatisplus.samples.generator.common.BaseEntity");
-
strategy.setEntityLombokModel(true);
-
// strategy.setSuperControllerClass("com.baomidou.mybatisplus.samples.generator.common.BaseController");
-
strategy.setInclude(scanner("表名"));
-
strategy.setSuperEntityColumns("id");
-
strategy.setControllerMappingHyphenStyle(true);
-
strategy.setTablePrefix(pc.getModuleName() "_");
-
mpg.setStrategy(strategy);
-
// 选择 freemarker 引擎需要指定如下加,注意 pom 依赖必须有!
-
mpg.setTemplateEngine(new FreemarkerTemplateEngine());
-
mpg.execute();
-
}
-
-
}
③
十五、MybatisX 快速开发插件
MybatisX 是一款基于 IDEA 的快速开发插件,为效率而生。
安装方法:打开 IDEA,进入 File -> Settings -> Plugins -> Browse Repositories,输入 mybatisx 搜索并安装。
功能: Java 与 XML 调回跳转 Mapper 方法自动生成 XML
这篇好文章是转载于:学新通技术网
- 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
- 本站站名: 学新通技术网
- 本文地址: /boutique/detail/tanhgigaga
-
photoshop保存的图片太大微信发不了怎么办
PHP中文网 06-15 -
《学习通》视频自动暂停处理方法
HelloWorld317 07-05 -
word里面弄一个表格后上面的标题会跑到下面怎么办
PHP中文网 06-20 -
Android 11 保存文件到外部存储,并分享文件
Luke 10-12 -
photoshop扩展功能面板显示灰色怎么办
PHP中文网 06-14 -
微信公众号没有声音提示怎么办
PHP中文网 03-31 -
excel下划线不显示怎么办
PHP中文网 06-23 -
excel打印预览压线压字怎么办
PHP中文网 06-22 -
TikTok加速器哪个好免费的TK加速器推荐
TK小达人 10-01 -
怎样阻止微信小程序自动打开
PHP中文网 06-13