当前位置: 首页 > news >正文

MyBatisPlus总结(1.0)

MyBatis-Plus

MyBatis-Plus介绍

MyBatis-Plus(简称MP)是一个MyBatis的增强工具,在MyBatis的基础上只做增强不做改变,为简化开发、提高效率而生

img

特性

  • 无侵入:只做增强不做改变,引入它不会对现有工程产生影响
  • 损耗小:启动既会自动注入基本CRUD,性能基本无损耗,直接面向对象操作
  • 强大的CRUD操作:内置通用Mapper、通用Service、仅仅通过少量配置即可实现单表大部分CRUD操作,更有强大的条件构造器,满足各类使用需求
  • 支持Lambda形式调用:通过Lambda表达式,方便的编写各类查询条件,无需再担心字段写错
  • 支持多种数据库:支持MySQL、MariaDB、Oracle、DB2、H2、HSQL、SQLite、Postgre
  • 支持主键自动生成:支持多达4种主键策略(内含分布式唯一ID生成器-Sequence),可自由配置,完美解决主键问题
  • 支持XML热加载:Mapper对应的xml支持热加载,对于简单的CRUD操作,甚至可以无XML启动
  • 支持自定义全局通用操作:支持全局通用方法注入
  • 支持关键词自动转义:支持数据库关键词自动转义,还可自定义关键词
  • 内置代码生成器:采用代码或者Maven插件可快速生成Mapper、Model、Service、Controller层代码,支持模板引擎,更有超多自定义配置
  • 内置分页插件:基于MyBatis物理分页,开发者无需关心具体操作,配置好插件之后,写分页等同于普通List查询
  • 内置性能分析插件:可输出Sql语句以及其执行时间,建议开发测试时启用该功能,能快速揪出慢查询
  • 内置全局拦截插件:提供全表delete、update操作智能分析阻断,也可自定义拦截规则,预防误操作
  • 内置sql注入剥离器:支持Sql注入剥离,有效预防Sql注入攻击

架构

img

快速开始

创建数据库以及表

-- 创建测试表
CREATE TABLE `tb_user` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
`user_name` varchar(20) NOT NULL COMMENT '用户名',
`password` varchar(20) NOT NULL COMMENT '密码',
`name` varchar(30) DEFAULT NULL COMMENT '姓名',
`age` int(11) DEFAULT NULL COMMENT '年龄',
`email` varchar(50) DEFAULT NULL COMMENT '邮箱',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;-- 插入测试数据
INSERT INTO `tb_user` (`id`, `user_name`, `password`, `name`, `age`, `email`) VALUES
('1', 'zhangsan', '123456', '张三', '18', 'test1@itcast.cn');
INSERT INTO `tb_user` (`id`, `user_name`, `password`, `name`, `age`, `email`) VALUES
('2', 'lisi', '123456', '李四', '20', 'test2@itcast.cn');
INSERT INTO `tb_user` (`id`, `user_name`, `password`, `name`, `age`, `email`) VALUES
('3', 'wangwu', '123456', '王五', '28', 'test3@itcast.cn');
INSERT INTO `tb_user` (`id`, `user_name`, `password`, `name`, `age`, `email`) VALUES
('4', 'zhaoliu', '123456', '赵六', '21', 'test4@itcast.cn');
INSERT INTO `tb_user` (`id`, `user_name`, `password`, `name`, `age`, `email`) VALUES
('5', 'sunqi', '123456', '孙七', '24', 'test5@itcast.cn');

创建工程

导入依赖

<dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.11</version><scope>test</scope></dependency><!-- 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>5.1.47</version></dependency><!-- 连接池 --><dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.0.11</version></dependency><!--简化bean代码的工具包--><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional><version>1.18.4</version></dependency><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-log4j12</artifactId><version>1.6.4</version></dependency>

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

MyBatis实现查询User

1、编写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><!--读取jdbc.properties--><properties resource="jdbc.properties"/><!--定义别名--><typeAliases><package name="com.dc.domain"/></typeAliases><!--数据库环境--><environments default="development"><environment id="development"><transactionManager type="JDBC"/><dataSource type="POOLED"><property name="driver" value="${driver}"/><property name="url" value="${url}"/><property name="username" value="${username}"/><property name="password" value="${password}"/></dataSource></environment></environments><!--加载mapper--><mappers><package name="com.dc.mapper"/></mappers>
</configuration>

2、编写jdbc.properties文件

driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/test?useUnicode=true&amp;characterEncoding=utf8&amp;autoReconnect=true&amp;allowMultiQueries=true&amp;useSSL=false"
username=root
password=root

3、编写User实体类对象

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {private Long id;private String username;private String password;private String name;private Integer age;private String email;@Overridepublic String toString() {return "User{" +"id=" + id +", username='" + username + '\'' +", password='" + password + '\'' +", name='" + name + '\'' +", age=" + age +", email='" + email + '\'' +'}';}
}

4、编写UserMapper接口

public interface UserMapper {List<User> findAll();
}

5、编写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.dc.mapper.UserMapper"><select id="findAll" resultType="user">select * from tb_user</select>
</mapper>

6、测试

public class Tes {private UserMapper userMapper;@Beforepublic void test() throws IOException {InputStream resource = Resources.getResourceAsStream("mybatis-config.xml");SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resource);SqlSession sqlSession = sqlSessionFactory.openSession(true);userMapper = sqlSession.getMapper(UserMapper.class);}@Testpublic void testUserList(){List<User> userList = userMapper.findAll();for (User user : userList) {System.out.println(user);}} 
}

结果:

img

MyBatis+MP实现查询User

1、将UserMapper继承BaseMapper,将拥有BaseMapper的所有方法:

public interface UserMapper extends BaseMapper<User> {List<User> findAll();
}

2、使用MP中的MybatisSqlSessionFactoryBuilder进程构建:

@Testpublic void testUserList1() throws IOException {InputStream resource = Resources.getResourceAsStream("mybatis-config.xml");SqlSessionFactory sqlSessionFactory = new MybatisSqlSessionFactoryBuilder().build(resource);SqlSession sqlSession = sqlSessionFactory.openSession(true);userMapper = sqlSession.getMapper(UserMapper.class);// 可以调用BaseMapper中定义的方法List<User> userList = userMapper.selectList(null);for (User user : userList) {System.out.println(user);}}

这是会报错:

img

解决方案:在User对象中添加@TableName,指定数据库表名

img

测试结果:

img

简单说明:

  • 由于使用了MybatisSqlSessionFactoryBuilder进行了构建,继承的BaseMapper中的方法就载入到了SqlSession中,所以就可以直接使用相关的方法:

Spring+Mybatis+MP

导入依赖

<!--spring--><dependency><groupId>org.springframework</groupId><artifactId>spring-webmvc</artifactId><version>5.1.6.RELEASE</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-jdbc</artifactId><version>5.1.6.RELEASE</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-test</artifactId><version>5.1.6.RELEASE</version></dependency>

实现查询user

1、编写jdbc.properties

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai
jdbc.username=root
jdbc.password=root

2、编写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
http://www.springframework.org/schema/context/spring-context.xsd"><!--配置所有properties文件--><context:property-placeholder location="classpath:jdbc.properties"></context:property-placeholder><!--定义数据源--><bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"><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><!--MP提供的SqlSessionFactory,完成了Spring与MP的整合--><bean id="sqlSessionFactory" class="com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean"><property name="dataSource" ref="dataSource"/><property name="configLocation" value="classpath:mybatis-config.xml"/></bean><bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"><property name="basePackage" value="com.dc.mapper"/></bean><beans default-autowire="byType"/></beans>

3、编写user对象以及UserMapper接口:

@Data
@AllArgsConstructor
@NoArgsConstructor
@TableName("tb_user")
public class User {private Long id;private String userName;private String password;private String name;private Integer age;private String email;@Overridepublic String toString() {return "User{" +"id=" + id +", username='" + userName + '\'' +", password='" + password + '\'' +", name='" + name + '\'' +", age=" + age +", email='" + email + '\'' +'}';}
}public interface UserMapper extends BaseMapper<User> {}

4、测试

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:applicationContext.xml")
public class TestMybatis {@Autowiredprivate UserMapper userMapper;@Testpublic void test() {List<User> users = userMapper.selectList(null);for (User user : users) {System.out.println(user);}}
}

结果:

img

SpringBoot+Mybatis+MP

导入依赖

<?xml version="1.0" encoding="UTF-8"?>
<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 https://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.7.5</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>com.dc</groupId><artifactId>smp</artifactId><version>0.0.1-SNAPSHOT</version><name>smp</name><description>smp</description><properties><java.version>17</java.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId></dependency><dependency><groupId>com.mysql</groupId><artifactId>mysql-connector-j</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><!--mybatis-plus的springboot支持--><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.1.1</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><configuration><excludes><exclude><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></exclude></excludes></configuration></plugin></plugins></build></project>

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

编写application.properties

spring.application.name=smp
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf8&autoReconnect=true&allowMultiQueries=true&useSSL=false
spring.datasource.username=root
spring.datasource.password=root

编写pojo

@Data
@AllArgsConstructor
@NoArgsConstructor
@TableName("tb_user")
public class User {private Long id;private String userName;private String password;private String name;private Integer age;private String email;@Overridepublic String toString() {return "User{" +"id=" + id +", username='" + userName + '\'' +", password='" + password + '\'' +", name='" + name + '\'' +", age=" + age +", email='" + email + '\'' +'}';}
}

编写mapper

@Mapper
public interface UserMapper extends BaseMapper<User> {}

编写启动类

@MapperScan("com.dc.mapper")
@SpringBootApplication
public class SmpApplication {public static void main(String[] args) {SpringApplication.run(SmpApplication.class, args);}}

测试用例

@RunWith(SpringRunner.class)
@SpringBootTest
public class UserMapperTest {@Autowiredprivate UserMapper userMapper;@Testpublic void test() {List<User> users = userMapper.selectList(null);for (User user : users) {System.out.println(user);}}
}

结果:

img

通用CRUD

插入操作

方法定义

/**
* 插入一条记录
*
* @param entity 实体对象
*/
int insert(T entity);

测试用例

    @Testpublic void testInsert() {User user = new User();user.setAge(20);user.setEmail("test@dc.com");user.setUserName("caocao");user.setName("曹操");user.setPassword("123456");int insert = userMapper.insert(user);System.out.println("result = " + insert);System.out.println(user.getId());}

结果:

img

img

可以看到,数据库已经写入到了数据库,但是,id的值不正确,目标是数据库自增长,实际是MP生成了id的值写入到了数据库

如何设置id的生成策略?

MP支持的id策略:

package com.baomidou.mybatisplus.annotation;
import lombok.Getter;
/**
* 生成ID类型枚举类
*/
@Getter
public enum IdType {/*** 数据库ID自增*/AUTO(0),/*** 该类型为未设置主键类型*/NONE(1),/*** 用户输入ID* <p>该类型可以通过自己注册自动填充插件进行填充</p>*/INPUT(2),/* 以下3种类型、只有当插入对象ID 为空,才自动填充。 *//*** 全局唯一ID (idWorker)*/ID_WORKER(3),/*** 全局唯一ID (UUID)*/UUID(4),/*** 字符串全局唯一ID (idWorker 的字符串表示)*/ID_WORKER_STR(5);private final int key;IdType(int key) {this.key = key;}
}

修改User对象

@Data
@AllArgsConstructor
@NoArgsConstructor
@TableName("tb_user")
public class User {// 指定id类型为自增@TableId(type = IdType.AUTO)private Long id;private String userName;private String password;private String name;private Integer age;private String email;@Overridepublic String toString() {return "User{" +"id=" + id +", username='" + userName + '\'' +", password='" + password + '\'' +", name='" + name + '\'' +", age=" + age +", email='" + email + '\'' +'}';}
}

结果:

img

@TableField

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

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

使用:

@Data
@AllArgsConstructor
@NoArgsConstructor
@TableName("tb_user")
public class User {// 指定id类型为自增@TableId(type = IdType.AUTO)private Long id;private String userName;private String password;private String name;private Integer age;// 解决字段名不一致@TableId(value = "email")private String email;// 该字段在数据库中不存在@TableField(exist = false)private String address;@Overridepublic String toString() {return "User{" +"id=" + id +", username='" + userName + '\'' +", password='" + password + '\'' +", name='" + name + '\'' +", age=" + age +", email='" + email + '\'' +'}';}
}

其他用法,如某字段不加入查询字段:

img

效果:

img

更新操作

在MP中,更新操作有2种,一种是根据id更新,另一种是根据条件更新

根据id更新

方法定义:

/**
* 根据 ID 修改
*
* @param entity 实体对象
*/
int updateById(@Param(Constants.ENTITY) T entity);

测试

@Testpublic void testUpdate() {User user = new User();// 主键user.setId(1L);// 更新字段user.setAge(21);// 根据id更新,更新不为null的字段userMapper.updateById(user);}

效果:

img

根据条件更新

方法定义:

/**
* 根据 whereEntity 条件,更新记录
*
* @param entity 实体对象 (set 条件值,可以为 null)
* @param updateWrapper 实体对象封装操作类(可以为 null,里面的 entity 用于生成 where 语句)
*/
int update(@Param(Constants.ENTITY) T entity, @Param(Constants.WRAPPER) Wrapper<T>
updateWrapper);

测试用例:

@Testpublic void testUpdate2() {User user = new User();// 更新字段user.setAge(22);// 更新条件QueryWrapper<User> wrapper = new QueryWrapper<>();// id为6的字段wrapper.eq("id", 6);// 执行更新操作int update = userMapper.update(user, wrapper);System.out.println("update =" + update);}

或者,通过UpdateWrapper进行更新:

@Testpublic void testUpdate3() {// 更新条件UpdateWrapper<User> wrapper = new UpdateWrapper<>();wrapper.eq("id", 6).set("age", 23);// 执行更新操作int update = userMapper.update(null, wrapper);System.out.println("update =" + update);}

测试结果:

img

删除操作

deleteById

方法定义:

/**
* 根据 ID 删除
*
* @param id 主键ID
*/
int deleteById(Serializable id);

测试用例:

@Testpublic void testDelete() {// 执行删除操作int i = userMapper.deleteById(6L);System.out.println("i = " + i);}

结果:

img

id为6的数据被删除

deleteByMap

方法定义:

/**
* 根据 columnMap 条件,删除记录
*
* @param columnMap 表字段 map 对象
*/
int deleteByMap(@Param(Constants.COLUMN_MAP) Map<String, Object> columnMap);

测试用例:

@Testpublic void testDeleteByMap() {HashMap<String, Object> columnMap = new HashMap<>();columnMap.put("age", 21);columnMap.put("name", "张三");// 将column中的元素设置为删除的条件,多个之间为and关系int i = userMapper.deleteByMap(columnMap);System.out.println("i = " + i);}

效果:

img

delete

方法定义

/**
* 根据 entity 条件,删除记录
*
* @param wrapper 实体对象封装操作类(可以为 null)
*/
int delete(@Param(Constants.WRAPPER) Wrapper<T> wrapper);

测试用例:

@Testpublic void testDelete1() {User user = new User();user.setAge(20);user.setName("张三");// 将实体对象进行封装,包装为操作条件QueryWrapper<User> wrapper = new QueryWrapper<>(user);int delete = userMapper.delete(wrapper);System.out.println("delete = "+ delete);}

效果:

img

deleteBatchIds

方法定义:

/**
* 删除(根据ID 批量删除)
*
* @param idList 主键ID列表(不能为 null 以及 empty)
*/
int deleteBatchIds(@Param(Constants.COLLECTION) Collection<? extends Serializable>
idList);

测试用例:

@Testpublic void testDeleteByMap1() {// 根据id集合批量删除int i = userMapper.deleteBatchIds(Arrays.asList(6L, 10L, 20L));System.out.println("i = " + i);}

效果:

img

查询操作

MP提供了多种查询操作,包括根据id查询、批量查询、查询单条数据、查询列表、分页查询等操作

selectById

方法定义

/**
* 根据 ID 查询
*
* @param id 主键ID
*/
T selectById(Serializable id);

测试用例

@Testpublic void testSelectById() {// 根据id查询数据User user = userMapper.selectById(2L);System.out.println("result = " + user);}

效果:

img

selectBatchIds

方法定义:

/**
* 查询(根据ID 批量查询)
*
* @param idList 主键ID列表(不能为 null 以及 empty)
*/
List<T> selectBatchIds(@Param(Constants.COLLECTION) Collection<? extends Serializable>
idList);

测试用例:

@Testpublic void testSelectBatchIds() {// 根据id批量查询数据List<User> users = userMapper.selectBatchIds(Arrays.asList(2L, 3L, 10L));for (User user : users) {System.out.println(user);}}

效果:

img

selectOne

方法定义:

/**
* 根据 entity 条件,查询一条记录
*
* @param queryWrapper 实体对象封装操作类(可以为 null)
*/
T selectOne(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);

测试用例:

@Testpublic void testSelectOne() {// 根据id批量查询数据QueryWrapper<User> wrapper = new QueryWrapper<>();wrapper.eq("name", "李四");// 根据条件查询一条数据,如果结果超过一条会报错User user = userMapper.selectOne(wrapper);System.out.println(user);}

效果:

img

selectCount

方法定义:

/**
* 根据 Wrapper 条件,查询总记录数
*
* @param queryWrapper 实体对象封装操作类(可以为 null)
*/
Integer selectCount(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);

测试用例:

@Testpublic void testSelectCount() {QueryWrapper<User> wrapper = new QueryWrapper<>();wrapper.gt("age", 23);// 根据条件查询数据条数Integer integer = userMapper.selectCount(wrapper);System.out.println("integer = " + integer);}

效果:

img

selectList

方法定义:

/**
* 根据 entity 条件,查询全部记录
*
* @param queryWrapper 实体对象封装操作类(可以为 null)
*/
List<T> selectList(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);

测试用例:

@Testpublic void testSelectList() {QueryWrapper<User> wrapper = new QueryWrapper<>();wrapper.gt("age", 23);// 根据条件查询数据List<User> users = userMapper.selectList(wrapper);for (User user : users) {System.out.println(user);}}

效果:

img

selectPage

方法定义:

/**
* 根据 entity 条件,查询全部记录(并翻页)
*
* @param page 分页查询条件(可以为 RowBounds.DEFAULT)
* @param queryWrapper 实体对象封装操作类(可以为 null)
*/
IPage<T> selectPage(IPage<T> page, @Param(Constants.WRAPPER) Wrapper<T> queryWrapper);

编写配置类:

@Configuration
@MapperScan("com.dc.mapper")
public class MybatisPlusConfig {/*** 分页插件* @param* @return*/@Beanpublic PaginationInterceptor paginationInterceptor() {return new PaginationInterceptor();}
}

测试用例:

@Testpublic void testSelectPage() {QueryWrapper<User> wrapper = new QueryWrapper<>();wrapper.gt("age", 18);Page<User> page = new Page<>(1, 1);// 根据条件查询数据IPage<User> userIPage = userMapper.selectPage(page, wrapper);System.out.println("数据总条数:" + userIPage.getTotal());System.out.println("总页数:" + userIPage.getPages());// 获取当前页面记录List<User> records = userIPage.getRecords();for (User record : records) {System.out.println(record);}}

效果:

img

配置

在MP中有大量配置,其中有一部分是MyBatis原生的配置,另一部分是MP的配置。

基本配置

configLocation

MyBatis配置文件位置,如果有单独的MyBatis配置,请将其路径配置到configLocaotion中。

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>

mapperLocations

MyBatis Mapper所对应的xml文件位置,如果在Mapper中有自定义方法,(xml中有自定义实现),需要进行该配置,告诉Mapper所对应的xml文件位置

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>

Maven多模块项目的扫描路径需以classpath*:开头(即加载多个jar包下的xml文件)

typeAliasesPackage

MyBatis别名包扫描路径,通过该属性可以给包中的类注册别名,注册后再mapper对应的xml文件中可以直接使用类名,而不用使用全限定的类名(即xml中调用的时候不用包含类名)

SpringBoot:

mybatis-plus.type-aliases-package = cn.itcast.mp.pojo

SpringMVC:

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

进阶配置

mapUnderscoreToCamelCase

  • 类型:boolean
  • 默认值:true

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

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

如果数据库命名符合规则,则无需使用@TableFiled注释指定数据库字段名

示例(SpringBoot):

#关闭自动驼峰映射,该参数不能和mybatis-plus.config-location同时存在
mybatis-plus.configuration.map-underscore-to-camel-case=false

cacheEnabled

  • 类型:boolean
  • 默认值:true

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

示例:

mybatis-plus.configuration.cache-enabled=false

DB策略配置

idType

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

全局默认主键类型,设置后,即可省略实体对象中的@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>

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接口的实现类关系如下:

img

AbstractWrapper和AbstractChainWrapper是重点实现的。

说明

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

allEq

说明

allEq(Map<R, V> params)
allEq(Map<R, V> params, boolean null2IsNull)
allEq(boolean condition, Map<R, V> params, boolean null2IsNull)
  • 全部eq(或个别isNuLL)

个别参数说明:paramskey为数据库字段名,value为字段值,nullisnuull:为true则在mapvaluenull时调用isNull方法,为false时则忽略valuenull的字段

  • 例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<R, V> filter, Map<R, V> params)
allEq(BiPredicate<R, V> filter, Map<R, V> params, boolean null2IsNull)
allEq(boolean condition, BiPredicate<R, V> filter, Map<R, V> params, boolean
null2IsNull)

个别参数说明:filter:过滤参数,是否允许字段传入比对条件中paramsnull2isNull:同上

  • 例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 = ‘老王’

测试用例:

@RunWith(SpringRunner.class)
@SpringBootTest
public class UserMapperTest {@Autowiredprivate UserMapper userMapper;@Testpublic 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
    • 不等于<>
  • 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, …)

测试用例:

@Testpublic void testEq() {QueryWrapper<User> wrapper = new QueryWrapper<>();wrapper.eq("password", "123456").ge("age", 20).in("name", "李四", "王五", "马六");List<User> users = userMapper.selectList(wrapper);for (User user : users) {System.out.println(user);}}

效果:

img

模糊查询

  • like
    • like ‘%值%’
    • 例: like(“name”, “王”) —> name like ‘%王%’
  • notlike
    • NOT LIKE ‘%值%’
  • likeLeft
    • LIKE ‘%值%’
    • 例: likeLeft(“name”, “王”) --> name like ‘%王’
  • likeRight
    • LIKE ‘值%’
    • 例: likeRight(“name”, “王”) --> name like ‘王%’

测试

@Testpublic void testLike() {QueryWrapper<User> wrapper = new QueryWrapper<>();wrapper.like("name", "王");List<User> users = userMapper.selectList(wrapper);for (User user : users) {System.out.println(user);}}

效果:

img

排序

  • orderBy
    • 排序: ORDER BY 字段…
    • 例:orderBy(true, true, “id”, “name”) --> order by id ASC, name ASC
  • orderByAsc
    • 排序: ORDER BY 字段,… ASC
    • 例:orderByAsx(“id”, “name”) —> order by id ASC, name ASC
  • orderByDesc
    • 排序:ORDER BY 字段,… DESC
    • 例:orderByDesc(“id”, “name”) --> order by id DESC, name DESC

测试用例:

@Testpublic void testOrder () {QueryWrapper<User> wrapper = new QueryWrapper<>();wrapper.orderByDesc("age");List<User> users = userMapper.selectList(wrapper);for (User user : users) {System.out.println(user);}}

效果:

img

逻辑查询

  • or
    • 拼接or
    • 主动调用or表示紧接着下一个方法不是用and连接(不调用or, 则默认使用and连接)
  • and
    • ANd嵌套
    • 例:and(i -> i.eq(“name”, “李白”).ne(“status”, “活着”)) --> and (name = ‘李白’ and status <> ‘活着’)

测试用例:

@Testpublic void testOr () {QueryWrapper<User> wrapper = new QueryWrapper<>();wrapper.eq("name", "李四").or().eq("age", 24);List<User> users = userMapper.selectList(wrapper);for (User user : users) {System.out.println(user);}}

效果:

img

select

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

@Testpublic void testSelect() {QueryWrapper<User> wrapper = new QueryWrapper<>();wrapper.select("id", "name", "age");List<User> users = userMapper.selectList(wrapper);for (User user : users) {System.out.println(user);}}

效果:

img

img

相关文章:

MyBatisPlus总结(1.0)

MyBatis-Plus MyBatis-Plus介绍 MyBatis-Plus&#xff08;简称MP&#xff09;是一个MyBatis的增强工具&#xff0c;在MyBatis的基础上只做增强不做改变&#xff0c;为简化开发、提高效率而生 特性 无侵入&#xff1a;只做增强不做改变&#xff0c;引入它不会对现有工程产生影…...

职场老油条表示真干不过,部门新来的00后测试员已把我卷崩溃,想离职了...

在程序员职场上&#xff0c;什么样的人最让人反感呢? 是技术不好的人吗?并不是。技术不好的同事&#xff0c;我们可以帮他。 是技术太强的人吗?也不是。技术很强的同事&#xff0c;可遇不可求&#xff0c;向他学习还来不及呢。 真正让人反感的&#xff0c;是技术平平&#x…...

【每日挠头算法题(1)】——旋转字符串|亲密字符串

文章目录 一、旋转字符串思路1思路2 二、亲密字符串思路 总结 一、旋转字符串 点我直达终点~ 思路1 前提&#xff1a;如果s串和goal串长度不等&#xff0c;则goal串不可能是s串旋转得来&#xff0c;直接返回false&#xff1b; 通过观察&#xff0c;可以发现每旋转一次&#…...

什么是 tokens,ChatGPT里面的Tokens如何计数?

什么是 tokens&#xff0c;ChatGPT里面的Tokens如何计数&#xff1f; 什么是 tokens&#xff1f; Tokens 可以被认为是词语的片段。在 API 处理提示之前&#xff0c;输入会被分解成 tokens。这些 tokens 并不会精确地在单词的开始或结束处切分 - tokens 可以包含尾随的空格甚…...

工业镜头分类、相关参数含义

一、工业镜头参数 1、焦距/后焦距 焦距是像方主面到像方焦点的距离。后焦距指光线离开镜头最后一片镜片表面到sensor感光面的距离&#xff0c;如8mm&#xff0c;16mm&#xff0c;25mm等&#xff1b; 焦距的大小决定着视角大小&#xff0c;焦距数值小&#xff0c;视角大&#…...

码蹄杯语言基础:数组(C语言)

码蹄集网站地址&#xff1a;https://www.matiji.net/exam/ojquestionlist ⭐MT1381逆序输出数组 定义一个长度为10的整型数组&#xff0c;输入10个数组元素的值&#xff0c;然后逆序输出他们 格式 输入格式&#xff1a; 输入10个数组元素的值&#xff0c;整型&#xff0c;空…...

DJ4-2 程序的装入和链接

目录 4.2.1 程序的装入 一、绝对装入方式 二 、可重定位装入方式 三、动态运行时装入方式 4.2.2 程序的链接 一、静态链接 二、装入时动态链接 三、运行时动态链接 在多道程序环境下&#xff0c;如果程序要运行&#xff0c;那么必须为之创建进程。而创建进程的第一件…...

开源项目合集....

likeshop开源商城系统&#xff0c;公众号商城、H5商城、微信小程序商城、抖音小程序商城、字节小程序商城、头条小程序商城、安卓App商城、苹果App商城代码全开源&#xff0c;免费商用。 适用场景&#xff1a;B2C商城、新零售商城、社交电商商城、分销系统商城、小程序商城、商…...

机器学习 | 降维问题

目录 一、主成分分析 二、奇异值分解 2.1 奇异值分解原理 2.2 奇异值分解实践 三、特征值与特征向量 一、主成分分析 主成分有如下特征&#xff1a; 每个主成分是原变量的线性组合&#xff1b;各个主成分之间互不相关&#xff1b;主成分按照方差贡献率从大到小依次排列&…...

Ubuntu20.04平台下使用二进制包部署MongoDB-6.0.4单实例

文章目录 1.1 准备服务器的基本信息1.2 操作系统上创建其用户1.3 部署MongoDB服务端1.4 部署MongoDB客户端1.5 部署MongoDB 27017实例1.5.1 创建相关目录1.5.2 准备配置文件1.5.3 准备启停脚本1.5.4 进行启停测试1.5.5 加入开机自启动 1.6 创建超级管理员用户1.6.1 创建本地的超…...

Snipaste工具推荐

Snipaste Snipaste 不只是截图&#xff0c;善用贴图功能将帮助你提升工作效率&#xff01; 新用户&#xff1f; 截图默认为 F1&#xff0c;贴图为 F3&#xff0c;然后请对照着 快捷键列表 按一遍&#xff0c;体会它们的用法&#xff0c;就入门啦&#xff01; 遇到了麻烦&…...

MinIO快速入门——在Linux系统上安装和启动

1、简介 MinIO 是一款基于Go语言发开的高性能、分布式的对象存储系统。客户端支持Java,Net,Python,Javacript, Golang语言。MinIO系统&#xff0c;非常适合于存储大容量非结构化的数据&#xff0c;例如图片、视频、日志文件、备份数据和容器/虚拟机镜像等。 2、环境搭建&#…...

07.JavaWeb-Vue+elementUI

1.Vue 功能替代JavaScript和jQuery&#xff0c;基于JavaScript实现的前端框架 1.1配置Vue 1.1.1引入vue库 方法一&#xff1a;通过cdn链接引入最新版本的vue&#xff08;可能会慢些&#xff09; <head><script src"https://cdn.jsdelivr.net/npm/vue">…...

经典面试题---【第一档】

1.如果你想new一个Quene&#xff0c;你有几种方式&#xff1f;他们之间的区别是什么&#xff1f; 2.Redis 是如何判断数据是否过期的呢&#xff1f; Redis 通过一个叫做过期字典&#xff08;可以看作是 hash 表&#xff09;来保存数据过期的时间。过期字典的键指向 Redis 数据…...

欧美同学会第三届“双创”大赛——空天装备产业赛区(浙江诸暨)正式启动,开启报名通道

6月8日&#xff0c;欧美同学会第三届“双创”大赛——空天装备产业赛区&#xff08;浙江诸暨&#xff09;启动仪式暨北京推介会圆满举行。活动由欧美同学会&#xff08;中国留学人员联谊会&#xff09;主办&#xff0c;中共浙江省委统战部支持&#xff0c;浙江省欧美同学会、中…...

python3 爬虫相关学习8:python 的常见报错内容 汇总收集

目录 1 拼写错误 AttributeError: NameError: 等等 2 类型错误 TypeError: 如字符串连接错误 TypeError: can only concatenate str (not “int“) to str 3 意外缩进 IndentationError: unexpected indent 4 找不到对应模块 ModuleNotFoundError: 5 语法错误 Syntax…...

活跃主机发现技术指南

活跃主机发现技术指南 1.活跃主机发现技术简介2.基于ARP协议的活跃主机发现技术3.基于ICMP协议的活跃主机发现技术4.基于TCP协议的活跃主机发现技术5.基于UDP协议的活跃主机发现技术6.基于SCTP协议的活跃主机发现技术7.主机发现技术的分析 1.活跃主机发现技术简介 在生活中有这…...

手机抓包fiddler配置及使用教程

本文基于Fiddler4讲解基本使用 fiddler抓包原理 注意&#xff1a;Fiddler 是以代理web服务器的形式工作的&#xff0c;它使用代理地址:127.0.0.1&#xff0c;端口:8888。当Fiddler退出的时候它会自动注销&#xff0c;这样就不会影响别的 程序。不过如果Fiddler非正常退出&…...

STM32单片机(四)第一节:OLED调试工具

❤️ 专栏简介&#xff1a;本专栏记录了从零学习单片机的过程&#xff0c;其中包括51单片机和STM32单片机两部分&#xff1b;建议先学习51单片机&#xff0c;其是STM32等高级单片机的基础&#xff1b;这样再学习STM32时才能融会贯通。 ☀️ 专栏适用人群 &#xff1a;适用于想要…...

自用的一些网址,码住!

京东羚珑智能抠图网站https://ling.jd.com/live/fm#all&#xff1a;主要用于商品抠图&#xff0c;而且还有多种直播背景设计&#xff0c;非常方便。国外的免费抠图网站https://www.remove.bg/zh/upload&#xff1a;有一个魔法棒的设计&#xff0c;可以自己选择抠图的范围和形状…...

Golang 面试经典题:map 的 key 可以是什么类型?哪些不可以?

Golang 面试经典题&#xff1a;map 的 key 可以是什么类型&#xff1f;哪些不可以&#xff1f; 在 Golang 的面试中&#xff0c;map 类型的使用是一个常见的考点&#xff0c;其中对 key 类型的合法性 是一道常被提及的基础却很容易被忽视的问题。本文将带你深入理解 Golang 中…...

渗透实战PortSwigger靶场-XSS Lab 14:大多数标签和属性被阻止

<script>标签被拦截 我们需要把全部可用的 tag 和 event 进行暴力破解 XSS cheat sheet&#xff1a; https://portswigger.net/web-security/cross-site-scripting/cheat-sheet 通过爆破发现body可以用 再把全部 events 放进去爆破 这些 event 全部可用 <body onres…...

前端导出带有合并单元格的列表

// 导出async function exportExcel(fileName "共识调整.xlsx") {// 所有数据const exportData await getAllMainData();// 表头内容let fitstTitleList [];const secondTitleList [];allColumns.value.forEach(column > {if (!column.children) {fitstTitleL…...

【Java_EE】Spring MVC

目录 Spring Web MVC ​编辑注解 RestController RequestMapping RequestParam RequestParam RequestBody PathVariable RequestPart 参数传递 注意事项 ​编辑参数重命名 RequestParam ​编辑​编辑传递集合 RequestParam 传递JSON数据 ​编辑RequestBody ​…...

今日学习:Spring线程池|并发修改异常|链路丢失|登录续期|VIP过期策略|数值类缓存

文章目录 优雅版线程池ThreadPoolTaskExecutor和ThreadPoolTaskExecutor的装饰器并发修改异常并发修改异常简介实现机制设计原因及意义 使用线程池造成的链路丢失问题线程池导致的链路丢失问题发生原因 常见解决方法更好的解决方法设计精妙之处 登录续期登录续期常见实现方式特…...

论文笔记——相干体技术在裂缝预测中的应用研究

目录 相关地震知识补充地震数据的认识地震几何属性 相干体算法定义基本原理第一代相干体技术&#xff1a;基于互相关的相干体技术&#xff08;Correlation&#xff09;第二代相干体技术&#xff1a;基于相似的相干体技术&#xff08;Semblance&#xff09;基于多道相似的相干体…...

Yolov8 目标检测蒸馏学习记录

yolov8系列模型蒸馏基本流程&#xff0c;代码下载&#xff1a;这里本人提交了一个demo:djdll/Yolov8_Distillation: Yolov8轻量化_蒸馏代码实现 在轻量化模型设计中&#xff0c;**知识蒸馏&#xff08;Knowledge Distillation&#xff09;**被广泛应用&#xff0c;作为提升模型…...

【Android】Android 开发 ADB 常用指令

查看当前连接的设备 adb devices 连接设备 adb connect 设备IP 断开已连接的设备 adb disconnect 设备IP 安装应用 adb install 安装包的路径 卸载应用 adb uninstall 应用包名 查看已安装的应用包名 adb shell pm list packages 查看已安装的第三方应用包名 adb shell pm list…...

MinIO Docker 部署:仅开放一个端口

MinIO Docker 部署:仅开放一个端口 在实际的服务器部署中,出于安全和管理的考虑,我们可能只能开放一个端口。MinIO 是一个高性能的对象存储服务,支持 Docker 部署,但默认情况下它需要两个端口:一个是 API 端口(用于存储和访问数据),另一个是控制台端口(用于管理界面…...

关于uniapp展示PDF的解决方案

在 UniApp 的 H5 环境中使用 pdf-vue3 组件可以实现完整的 PDF 预览功能。以下是详细实现步骤和注意事项&#xff1a; 一、安装依赖 安装 pdf-vue3 和 PDF.js 核心库&#xff1a; npm install pdf-vue3 pdfjs-dist二、基本使用示例 <template><view class"con…...