MyBatisPlus总结(1.0)
MyBatis-Plus
MyBatis-Plus介绍
MyBatis-Plus(简称MP)是一个MyBatis的增强工具,在MyBatis的基础上只做增强不做改变,为简化开发、提高效率而生
特性
- 无侵入:只做增强不做改变,引入它不会对现有工程产生影响
- 损耗小:启动既会自动注入基本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注入攻击
架构
快速开始
创建数据库以及表
-- 创建测试表
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&characterEncoding=utf8&autoReconnect=true&allowMultiQueries=true&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);}}
}
结果:
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);}}
这是会报错:
解决方案:在User对象中添加@TableName,指定数据库表名
测试结果:
简单说明:
- 由于使用了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);}}
}
结果:
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);}}
}
结果:
通用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());}
结果:
可以看到,数据库已经写入到了数据库,但是,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 + '\'' +'}';}
}
结果:
@TableField
在MP中通过@TableField注解可以指定字段的一些属性,常常解决的问题有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 + '\'' +'}';}
}
其他用法,如某字段不加入查询字段:
效果:
更新操作
在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);}
效果:
根据条件更新
方法定义:
/**
* 根据 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);}
测试结果:
删除操作
deleteById
方法定义:
/**
* 根据 ID 删除
*
* @param id 主键ID
*/
int deleteById(Serializable id);
测试用例:
@Testpublic void testDelete() {// 执行删除操作int i = userMapper.deleteById(6L);System.out.println("i = " + i);}
结果:
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);}
效果:
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);}
效果:
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);}
效果:
查询操作
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);}
效果:
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);}}
效果:
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);}
效果:
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);}
效果:
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);}}
效果:
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);}}
效果:
配置
在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接口的实现类关系如下:
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)
个别参数说明:
params
:key
为数据库字段名,value
为字段值,nullisnuull
:为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<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
:过滤参数,是否允许字段传入比对条件中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 = ‘老王’
测试用例:
@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);}}
效果:
模糊查询
- 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);}}
效果:
排序
- 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);}}
效果:
逻辑查询
- 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);}}
效果:
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);}}
效果:
相关文章:

MyBatisPlus总结(1.0)
MyBatis-Plus MyBatis-Plus介绍 MyBatis-Plus(简称MP)是一个MyBatis的增强工具,在MyBatis的基础上只做增强不做改变,为简化开发、提高效率而生 特性 无侵入:只做增强不做改变,引入它不会对现有工程产生影…...

职场老油条表示真干不过,部门新来的00后测试员已把我卷崩溃,想离职了...
在程序员职场上,什么样的人最让人反感呢? 是技术不好的人吗?并不是。技术不好的同事,我们可以帮他。 是技术太强的人吗?也不是。技术很强的同事,可遇不可求,向他学习还来不及呢。 真正让人反感的,是技术平平&#x…...

【每日挠头算法题(1)】——旋转字符串|亲密字符串
文章目录 一、旋转字符串思路1思路2 二、亲密字符串思路 总结 一、旋转字符串 点我直达终点~ 思路1 前提:如果s串和goal串长度不等,则goal串不可能是s串旋转得来,直接返回false; 通过观察,可以发现每旋转一次&#…...

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

工业镜头分类、相关参数含义
一、工业镜头参数 1、焦距/后焦距 焦距是像方主面到像方焦点的距离。后焦距指光线离开镜头最后一片镜片表面到sensor感光面的距离,如8mm,16mm,25mm等; 焦距的大小决定着视角大小,焦距数值小,视角大&#…...
码蹄杯语言基础:数组(C语言)
码蹄集网站地址:https://www.matiji.net/exam/ojquestionlist ⭐MT1381逆序输出数组 定义一个长度为10的整型数组,输入10个数组元素的值,然后逆序输出他们 格式 输入格式: 输入10个数组元素的值,整型,空…...

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

开源项目合集....
likeshop开源商城系统,公众号商城、H5商城、微信小程序商城、抖音小程序商城、字节小程序商城、头条小程序商城、安卓App商城、苹果App商城代码全开源,免费商用。 适用场景:B2C商城、新零售商城、社交电商商城、分销系统商城、小程序商城、商…...
机器学习 | 降维问题
目录 一、主成分分析 二、奇异值分解 2.1 奇异值分解原理 2.2 奇异值分解实践 三、特征值与特征向量 一、主成分分析 主成分有如下特征: 每个主成分是原变量的线性组合;各个主成分之间互不相关;主成分按照方差贡献率从大到小依次排列&…...

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 不只是截图,善用贴图功能将帮助你提升工作效率! 新用户? 截图默认为 F1,贴图为 F3,然后请对照着 快捷键列表 按一遍,体会它们的用法,就入门啦! 遇到了麻烦&…...

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

07.JavaWeb-Vue+elementUI
1.Vue 功能替代JavaScript和jQuery,基于JavaScript实现的前端框架 1.1配置Vue 1.1.1引入vue库 方法一:通过cdn链接引入最新版本的vue(可能会慢些) <head><script src"https://cdn.jsdelivr.net/npm/vue">…...

经典面试题---【第一档】
1.如果你想new一个Quene,你有几种方式?他们之间的区别是什么? 2.Redis 是如何判断数据是否过期的呢? Redis 通过一个叫做过期字典(可以看作是 hash 表)来保存数据过期的时间。过期字典的键指向 Redis 数据…...

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

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抓包原理 注意:Fiddler 是以代理web服务器的形式工作的,它使用代理地址:127.0.0.1,端口:8888。当Fiddler退出的时候它会自动注销,这样就不会影响别的 程序。不过如果Fiddler非正常退出&…...

STM32单片机(四)第一节:OLED调试工具
❤️ 专栏简介:本专栏记录了从零学习单片机的过程,其中包括51单片机和STM32单片机两部分;建议先学习51单片机,其是STM32等高级单片机的基础;这样再学习STM32时才能融会贯通。 ☀️ 专栏适用人群 :适用于想要…...
自用的一些网址,码住!
京东羚珑智能抠图网站https://ling.jd.com/live/fm#all:主要用于商品抠图,而且还有多种直播背景设计,非常方便。国外的免费抠图网站https://www.remove.bg/zh/upload:有一个魔法棒的设计,可以自己选择抠图的范围和形状…...

Redis相关知识总结(缓存雪崩,缓存穿透,缓存击穿,Redis实现分布式锁,如何保持数据库和缓存一致)
文章目录 1.什么是Redis?2.为什么要使用redis作为mysql的缓存?3.什么是缓存雪崩、缓存穿透、缓存击穿?3.1缓存雪崩3.1.1 大量缓存同时过期3.1.2 Redis宕机 3.2 缓存击穿3.3 缓存穿透3.4 总结 4. 数据库和缓存如何保持一致性5. Redis实现分布式…...

【入坑系列】TiDB 强制索引在不同库下不生效问题
文章目录 背景SQL 优化情况线上SQL运行情况分析怀疑1:执行计划绑定问题?尝试:SHOW WARNINGS 查看警告探索 TiDB 的 USE_INDEX 写法Hint 不生效问题排查解决参考背景 项目中使用 TiDB 数据库,并对 SQL 进行优化了,添加了强制索引。 UAT 环境已经生效,但 PROD 环境强制索…...

Opencv中的addweighted函数
一.addweighted函数作用 addweighted()是OpenCV库中用于图像处理的函数,主要功能是将两个输入图像(尺寸和类型相同)按照指定的权重进行加权叠加(图像融合),并添加一个标量值&#x…...
全面解析各类VPN技术:GRE、IPsec、L2TP、SSL与MPLS VPN对比
目录 引言 VPN技术概述 GRE VPN 3.1 GRE封装结构 3.2 GRE的应用场景 GRE over IPsec 4.1 GRE over IPsec封装结构 4.2 为什么使用GRE over IPsec? IPsec VPN 5.1 IPsec传输模式(Transport Mode) 5.2 IPsec隧道模式(Tunne…...
稳定币的深度剖析与展望
一、引言 在当今数字化浪潮席卷全球的时代,加密货币作为一种新兴的金融现象,正以前所未有的速度改变着我们对传统货币和金融体系的认知。然而,加密货币市场的高度波动性却成为了其广泛应用和普及的一大障碍。在这样的背景下,稳定…...
webpack面试题
面试题:webpack介绍和简单使用 一、webpack(模块化打包工具)1. webpack是把项目当作一个整体,通过给定的一个主文件,webpack将从这个主文件开始找到你项目当中的所有依赖文件,使用loaders来处理它们&#x…...
Java并发编程实战 Day 11:并发设计模式
【Java并发编程实战 Day 11】并发设计模式 开篇 这是"Java并发编程实战"系列的第11天,今天我们聚焦于并发设计模式。并发设计模式是解决多线程环境下常见问题的经典解决方案,它们不仅提供了优雅的设计思路,还能显著提升系统的性能…...

CMS内容管理系统的设计与实现:多站点模式的实现
在一套内容管理系统中,其实有很多站点,比如企业门户网站,产品手册,知识帮助手册等,因此会需要多个站点,甚至PC、mobile、ipad各有一个站点。 每个站点关联的有站点所在目录及所属的域名。 一、站点表设计…...
PostgreSQL 与 SQL 基础:为 Fast API 打下数据基础
在构建任何动态、数据驱动的Web API时,一个稳定高效的数据存储方案是不可或缺的。对于使用Python FastAPI的开发者来说,深入理解关系型数据库的工作原理、掌握SQL这门与数据库“对话”的语言,以及学会如何在Python中操作数据库,是…...
【大厂机试题解法笔记】矩阵匹配
题目 从一个 N * M(N ≤ M)的矩阵中选出 N 个数,任意两个数字不能在同一行或同一列,求选出来的 N 个数中第 K 大的数字的最小值是多少。 输入描述 输入矩阵要求:1 ≤ K ≤ N ≤ M ≤ 150 输入格式 N M K N*M矩阵 输…...