MyBatis-Plus (MP) только расширяет, а не изменяет на основе MyBatis, что упрощает разработку и повышает эффективность.
Эта статья основана наРуководство по началу работы с MyBatis-PlusВидео, подведение итогов после обучения. Если интересно, можете глянуть, для новичков очень полезно.
Курс интегрирован по типу SpringBoot + MyBatis-Plus.
адрес проекта
В статье может быть не понятно описано, или если вы хотите увидеть код, вы можете клонировать репозиторий
Предварительная конфигурация
Конфигурация базы данных и таблиц
В этом исследовании используется только одна библиотека и одна таблица с именем библиотеки mp и именем таблицы mp_user. Просто скопируйте его в инструмент sql и импортируйте.
/*
Navicat Premium Data Transfer
Source Server : mac
Source Server Type : MySQL
Source Server Version : 50716
Source Host : localhost:3306
Source Schema : mp
Target Server Type : MySQL
Target Server Version : 50716
File Encoding : 65001
Date: 30/07/2020 23:12:46
*/
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for mp_user
-- ----------------------------
DROP TABLE IF EXISTS `mp_user`;
CREATE TABLE `mp_user` (
`id` bigint(20) NOT NULL COMMENT '主键',
`name` varchar(30) DEFAULT NULL COMMENT '姓名',
`age` int(11) DEFAULT NULL COMMENT '年龄',
`email` varchar(50) DEFAULT NULL COMMENT '邮箱',
`manager_id` bigint(20) DEFAULT NULL COMMENT '直属上级id',
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
PRIMARY KEY (`id`),
KEY `manager_fk` (`manager_id`),
CONSTRAINT `manager_fk` FOREIGN KEY (`manager_id`) REFERENCES `mp_user` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of mp_user
-- ----------------------------
BEGIN;
INSERT INTO `mp_user` VALUES (1087982257332887553, '大boss', 40, 'boss@baomidou.com', NULL, '2019-01-11 14:20:20');
INSERT INTO `mp_user` VALUES (1088248166370832385, '王天风', 26, 'wtf2@baomidou.com', 1087982257332887553, '2019-02-05 11:12:22');
INSERT INTO `mp_user` VALUES (1088250446457389058, '李艺伟', 32, 'lyw2019@baomidou.com', 1088248166370832385, '2019-02-14 08:31:16');
INSERT INTO `mp_user` VALUES (1094590409767661570, '张雨琪', 31, 'zjq@baomidou.com', 1088248166370832385, '2019-01-14 09:15:15');
INSERT INTO `mp_user` VALUES (1094592041087729666, '刘红雨', 32, 'lhm@baomidou.com', 1088248166370832385, '2019-01-14 09:48:16');
INSERT INTO `mp_user` VALUES (1288460195017072641, '刘明强', 31, NULL, 1088248166370832385, '2020-07-29 21:03:44');
INSERT INTO `mp_user` VALUES (1288842439342780417, '张强', 29, 'lh@baomidou.com', 1088248166370832385, '2020-07-30 22:23:33');
INSERT INTO `mp_user` VALUES (1288848935841488897, '刘花', 29, 'lh@baomidou.com', 1088248166370832385, '2020-07-30 22:48:27');
COMMIT;
SET FOREIGN_KEY_CHECKS = 1;
Конфигурация зависимостей
Укажите родительский проект SpringBoot
- Зависит от SpringBootStarter
- ломбок, сгенерировать, установить, уменьшить код шаблона
- Стартер предоставлен нам MyBatis-Plus
- Последний пакет драйверов mysql.
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.immoc.mybatisplus</groupId>
<artifactId>immoc-mybatis-plus</artifactId>
<version>1.0-SNAPSHOT</version>
<modules>
<module>first</module>
<module>crud</module>
</modules>
<packaging>pom</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<mybatis.starter.version>3.1.0</mybatis.starter.version>
</properties>
<!-- Spring Boot Starter 父工程 -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.3.RELEASE</version>
</parent>
<dependencies>
<!-- SpringBoot启动器 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<!-- SpringBoot test启动器 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<!-- lombok简化Java代码 -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!-- MyBatis-Plus启动器 -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>${mybatis.starter.version}</version>
</dependency>
<!-- MySQL jdbc 驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
</dependencies>
</project>
База данных и соответствующая конфигурация MyBaits-Plus
В каталоге ресурсов создайтеapplication.yml
документ. Конфигурация:
- Имя элемента
- 4 основные конфигурации базы данных, измените свое имя пользователя и пароль mysql!
- уровень печати журнала
- Конфигурация MyBatis-Plus и т.д., комментарии написаны очень четко, поэтому повторяться не буду.
spring:
application:
name: crud
#配置数据库
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/mp?useSSL=false&serverTimezone=GMT%2B8
username: root
password: hezihao123
#配置Log打印
logging:
level:
root: warn
com.imooc.mybatisplus: trace
pattern:
console: '%p%m%n'
mybatis-plus:
#配置mapper文件的位置,注意,如果你是maven多模块下使用,路径前需要加classpath*,即加载多个jar包下的xml文件
mapper-locations:
- classpath*:com/imooc/mybatisplus/mapper/*
global-config:
db-config:
#全局id策略
id-type: id_worker
#字段生成sql的where策略,默认实体中的字段为null时,不添加到sql中,如果想为null,也添加到sql语句中,则使用ignored
#一般不设置为ignored,因为在update语句中,如果不设置值,就会用null覆盖掉原有的值。一般我们是希望设置值的才更新,为null则不更新
#not_empty,如果字段值为null或者空字符串,会忽略掉,不添加到sql语句中
field-strategy: default
#统一表名前缀
#table-prefix: mp_
#数据库表是否使用下划线间隔命名,默认为true
table-underline: true
#传统的mybatis配置文件位置
#config-location: classpath:mybatis-config.xml
#实体别名包配置
type-aliases-package: com.imooc.mybatisplus.entity
#注意configuration不能和config-location同时出现,不然会报错
configuration:
#驼峰转下划线(实体类用驼峰,数据库表字段用下划线),默认为true
map-underscore-to-camel-case: true
Настройте файл конфигурации оригинального MyBatis
По сути, конфигурация MyBatis будет настроена наapplication.yml
, но есть некоторые специфичные для MyBatis конфигурации, которые все еще можно поместить в исходные файлы конфигурации, такие как вторичный и третичный кэши и т. д.
Создал в папке ресурсов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>
</configuration>
Настройте плагин пейджинга MyBatis-Plus
Создайте пакет конфигурации и добавьте класс MyBatisPlusConfig, который представляет собой класс конфигурации, предоставляющий экземпляр подключаемого модуля пейджинга PaginationInterceptor.
@Configuration
public class MyBatisPlusConfig {
/**
* MyBatisPlus的分页插件
*/
@Bean
public PaginationInterceptor paginationInterceptor() {
return new PaginationInterceptor();
}
}
Запись приложения
SpringBoot требует, чтобы мы предоставили запись с основным методом, например, мы предоставляем класс Application для запуска
Примечание. Используйте аннотацию @MapperScan, чтобы указать путь к пакету, сканируемому MyBatis.
@SpringBootApplication
//指定MyBatis扫描的包路径
@MapperScan("com.imooc.mybatisplus.dao")
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
Создайте класс сущности, соответствующий таблице
- Аннотация @Data для создания методов получения и установки классов сущностей
- аннотацию @EqualsAndHashCode, сгенерируйте методы equals и hashcode и укажите, что не следует вызывать методы equals и hashcode родительского класса.
- В аннотации @TableName указывается имя таблицы, соответствующее классу сущностей.Если имя таблицы и имя класса сущностей совпадают, его можно опустить, но если они несовместимы, аннотация требуется для указания имени таблицы.
- Аннотация @TableId указывает, что переменная-член класса сущности является полем первичного ключа в таблице базы данных, а атрибут value указывает имя первичного ключа в таблице. Имя первичного ключа по умолчанию — id. Если два имени согласуются с базой данных, их можно опустить. Если они несовместимы, их необходимо добавить.
- Аннотация @TableField указывает, что переменная-член является полем, соответствующим базе данных.Если имя переменной-члена и поля таблицы совпадают, его можно опустить.Если они несовместимы, его необходимо добавить.
- атрибут value, используемый для указания соответствующего имени поля таблицы
- Атрибут стратегии может указывать стратегию поля. По умолчанию, когда поле не равно нулю, операции вставки и обновления будут добавлены в поле данных инструкции sql. Можно настроить различные стратегии, например FieldStrategy.NOT_EMPTY, когда поле не является нулевым и ненулевым. Когда строка, добавляется только оператор sql
- Атрибут exists указывает, что переменная-член не является полем в таблице базы данных. Во время CRUD это поле не будет добавлено в sql.
@Data
@EqualsAndHashCode(callSuper = false)
@TableName("mp_user")
public class User {
/**
* 主键
* 注解@TableId,标识字段为主键,如变量名和数据库字段名不一致,可指定
*/
//@TableId(value = "id")
/**
* 主键策略
* 1.IdType.AUTO:数据库自增
* 2.IdType.NONE:不配置,默认雪花算法
* 以下3种策略,主键的Id不能设置值,才会生效
* 3.IdType.ID_WORKER:雪花算法,数值类型
* 4.IdType.UUID:UUID,字符串类型
* 5.IdType.ID_WORKER_STR,雪花算法,字符串类型
*/
@TableId(value = "id")
private Long userId;
/**
* 姓名
* 注解@TableField,标识为数据库字段,如变量名和数据库字段名不一致,可指定
* condition属性,用作在使用实体作为查询条件给MyBatis-Plus直接查询时,可以指定字段是作为等值还是模糊查询,或不等于等条件(默认是等值)
*/
//@TableField(value = "name", condition = SqlCondition.LIKE)
/**
* strategy属性,字段策略,NOT_EMPTY会忽略为null和空字符串的值
*/
//@TableField(value = "name", strategy = FieldStrategy.NOT_EMPTY)
@TableField(value = "name")
private String readName;
/**
* 年龄
*/
private Integer age;
/**
* 邮箱
*/
private String email;
/**
* 直属上级
*/
private Long managerId;
/**
* 创建时间
*/
private LocalDateTime createTime;
/**
* 备注,非数据库字段,默认MyBatis-Plus会将实体的所有变量名作为数据库字段,如果没有字段就会报错
* 标识为非数据库字段的3种方式:
* 1.transient关键字,标识该字段不参与序列化
* 2.将字段使用static静态标识,但会导致全类共用一个属性,一般不会用
* 3.使用@TableField注解,将exist属性设置为false,来表示不是数据库字段
*/
//private transient String remark;
//private static String remark;
@TableField(exist = false)
private String remark;
}
Настройте Dao или вызовите Mapper
UserMapper — это интерфейс Mapper, соответствующий классу User. Каждый пользовательский интерфейс Mapper наследует интерфейс BaseMapper, который в общем определяет класс объекта операции.
BaseMapper предоставляет множество операций с одной таблицей, пакетных операций, условных запросов, запросов на подкачку и т. д., общих методов. Наш пользовательский интерфейс Mapper записывает только специальные методы операций, такие как пользовательские запросы на объединение нескольких таблиц и т. д., которые пока не добавляются и будут добавлены, когда пользовательские методы будут объяснены позже.
public interface UserMapper extends BaseMapper<User> {
}
Тест CRUD
- Вставьте тест, под тестовым пакетом создайте новый тестовый класс InsertTest
Insert вызывает метод insert() UserMapper, который предоставляется BaseMapper.
//指定可以在Spring环境下使用Junit测试
@RunWith(SpringRunner.class)
//标识该类是SpringBoot测试类,并指定启动类
@SpringBootTest(classes = Application.class)
public class InsertTest {
@Autowired
private UserMapper userMapper;
@Test
public void insert() {
//插入
User user = new User();
user.setReadName("刘明强");
user.setAge(31);
user.setManagerId(1088248166370832385L);
user.setCreateTime(LocalDateTime.now());
int rows = userMapper.insert(user);
System.out.println("影响记录数:" + rows);
}
@Test
public void insert2() {
//插入
User user = new User();
user.setReadName("向中");
user.setAge(25);
user.setManagerId(1088248166370832385L);
user.setEmail("xd@baomidou.com");
user.setCreateTime(LocalDateTime.now());
user.setRemark("我是一个备注信息");
int rows = userMapper.insert(user);
System.out.println("影响记录数:" + rows);
}
}
- Удалите тест, под тестовым пакетом создайте новый тестовый класс DeleteTest
Удалить, BaseMapper предоставляет несколько
- deleteById, удалить по первичному ключу
- deleteByMap, поместите условие удаления в карту и удалите ее.
- deleteBatchIds, удаление идентификатора пакета
- удалить, передать в Wrapper, класс Wrapper является условным конструктором, и в конструкторе есть методы условного добавления, такие как или, получить больше, чем и т. д. Например, вот для удаления записей, возраст которых 27 или старше 41 года.
@RunWith(SpringRunner.class)
@SpringBootTest(classes = Application.class)
public class DeleteTest {
@Autowired
private UserMapper userMapper;
/**
* 根据主键Id删除
*/
@Test
public void deleteById() {
int rows = userMapper.deleteById(1288677289033801729L);
System.out.println("影响记录数:" + rows);
}
/**
* 提供一个Map,Map中记录删除条件,进行删除
*/
@Test
public void deleteByMap() {
HashMap<String, Object> columnMap = new HashMap<>();
columnMap.put("id", 1288676754557825026L);
columnMap.put("age", 25);
int rows = userMapper.deleteByMap(columnMap);
System.out.println("影响记录数:" + rows);
}
/**
* 传入多个id,进行批量删除
*/
@Test
public void deleteIds() {
int rows = userMapper.deleteBatchIds(Arrays.asList(1288461659789660161L,
1288671248736870402L, 1288676285735272450L));
System.out.println("影响记录数:" + rows);
}
/**
* 使用条件构造器,进行删除
*/
@Test
public void deleteByWrapper() {
LambdaQueryWrapper<User> lambdaQuery = Wrappers.lambdaQuery();
lambdaQuery.eq(User::getAge, 27)
.or()
.gt(User::getAge, 41);
int rows = userMapper.delete(lambdaQuery);
System.out.println("影响记录数:" + rows);
}
}
- Обновите тест, под тестовым пакетом создайте тестовый класс UpdateTest
BaseMapper предоставляет следующие методы обновления:
- updateById, обновление в соответствии с идентификатором первичного ключа объекта
- update, передать объект и класс Wrapper, объект устанавливает обновленное значение и условие конфигурации Wrapper.
- update, который похож на второй, за исключением того, что при создании класса Wrapper передается класс сущности.
- update, используйте только Wrapper, класс сущности передает значение null, а значение обновления устанавливается методом set Wrapper
- обновление, как и четвертое, заменить класс Wrapper на LambdaXXXWrapper, поддерживающий лямбда-выражения
- Метод update не находится в классе Mapper, но передается в Mapper при создании Wrapper.При вызове метода update Wrapper косвенно вызывается класс Mapper Лиги чемпионов.
@RunWith(SpringRunner.class)
@SpringBootTest(classes = Application.class)
public class UpdateTest {
@Autowired
private UserMapper userMapper;
/**
* 更新条件和更新信息放在实体,按主键Id更新
*/
@Test
public void updateById() {
User user = new User();
user.setUserId(1088248166370832385L);
user.setAge(26);
user.setEmail("wtf2@baomidou.com");
int rows = userMapper.updateById(user);
System.out.println("影响记录数:" + rows);
}
/**
* 更新信息放在实体,更新条件使用条件构造器,进行更新
*/
@Test
public void updateByWrapper() {
UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();
updateWrapper.eq("name", "李艺伟")
.eq("age", 28);
User user = new User();
user.setEmail("lyw2019@baomidou.com");
user.setAge(29);
int rows = userMapper.update(user, updateWrapper);
System.out.println("影响记录数:" + rows);
}
/**
* UpdateWrapper创建时传入更新实体
*/
@Test
public void updateByWrapper2() {
User whereUser = new User();
whereUser.setReadName("李艺伟");
whereUser.setEmail("lyw2019@baomidou.com");
whereUser.setAge(29);
UpdateWrapper<User> updateWrapper = new UpdateWrapper<>(whereUser);
int rows = userMapper.update(whereUser, updateWrapper);
System.out.println("影响记录数:" + rows);
}
/**
* 通过UpdateWrapper进行条件设置,并且通过set方法设置新值
*/
@Test
public void updateByWrapper3() {
UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();
updateWrapper.eq("name", "李艺伟")
.eq("age", 29)
.set("age", 30);
int rows = userMapper.update(null, updateWrapper);
System.out.println("影响记录数:" + rows);
}
/**
* 通过UpdateWrapper进行条件设置,并且通过set方法设置新值
*/
@Test
public void updateByWrapperLambda() {
LambdaUpdateWrapper<User> updateWrapper = Wrappers.lambdaUpdate();
updateWrapper.eq(User::getReadName, "李艺伟")
.eq(User::getAge, 30)
.set(User::getAge, 31);
int rows = userMapper.update(null, updateWrapper);
System.out.println("影响记录数:" + rows);
}
/**
* 另外一种Lambda表达式方式
*/
@Test
public void updateByWrapperLambdaChain() {
LambdaUpdateChainWrapper<User> updateWrapper = new LambdaUpdateChainWrapper<>(userMapper);
boolean isUpdateSuccess = updateWrapper.eq(User::getReadName, "李艺伟")
.eq(User::getAge, 31)
.set(User::getAge, 32)
.update();
System.out.println("是否更新成功:" + isUpdateSuccess);
}
}
- Тест запроса, в тестовом пакете добавьте тестовый класс RetrieveTest
- selectById, запрос по идентификатору первичного ключа
- selectBatchIds, запрос идентификатора пакета
- selectByMap, поместите условия запроса в карту и запросите
- selectList, предоставляющий экземпляр класса QueryWrapper, используемый в качестве конструктора условия запроса.
- selectMaps предоставляет экземпляр класса QueryWrapper, который используется в качестве конструктора условия запроса, но возвращаемый результат запроса является не объектом класса сущности, а картой, в которой хранятся все атрибуты и значения.
- selectObjs, предоставляет экземпляр класса QueryWrapper, который используется в качестве конструктора условия запроса.Этот метод будет возвращать только атрибуты и значения первого столбца результата запроса (остальные поля запрашиваются в sql, но selectObjs( ) метод выбирает только первый столбец Данные столбца, его можно использовать, когда возвращается только первый столбец)
- selectCount, статистический запрос, результаты статистического запроса, количество записей
- selectOne, запрашивается только 1 часть данных (должен быть только 1 результат запроса, более одного сообщит об ошибке)
- selectList, используйте LambdaQueryWrapper для использования лямбда-выражений (преимущества: имитация написания, если это распространенный способ, передать имя поля базы данных, если оно неверно, оно сообщит об ошибке, лямбда-выражения используют ссылки на методы для получения информации о поле)
@RunWith(SpringRunner.class)
@SpringBootTest(classes = Application.class)
public class RetrieveTest {
@Autowired
private UserMapper userMapper;
/**
* 根据主键Id查询
*/
@Test
public void selectById() {
User user = userMapper.selectById(1094590409767661570L);
System.out.println(user);
}
/**
* 一次使用多个Id进行查询
*/
@Test
public void selectIds() {
List<Long> idList = Arrays.asList(1088248166370832385L, 1288460195017072641L, 1094590409767661570L);
List<User> userList = userMapper.selectBatchIds(idList);
for (User user : userList) {
System.out.println(user);
}
}
/**
* 使用Mao存放查询字段和条件来进行查询
*/
@Test
public void selectByMap() {
//Map存放查询条件,注意key存放的是数据库的字段名,而不是实体中的变量名
HashMap<String, Object> columnMap = new HashMap<>();
columnMap.put("name", "王天风");
columnMap.put("age", 25);
List<User> userList = userMapper.selectByMap(columnMap);
for (User user : userList) {
System.out.println(user);
}
}
/**
* 使用条件构造器进行查询
* <p>
* 需求:
* 名字中包含"雨",并且年龄小于40
* sql: name like %雨% and age < 40
*/
@Test
public void selectByWrapper() {
//直接创建一个条件构造器,获取使用Wrappers工具类
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
//QueryWrapper<User> queryWrapper = Wrappers.query();
queryWrapper
//模糊查询,注意这里的字段都是数据库字段,而不是实体的变量名
.like("name", "雨")
//小于
.lt("age", 40);
List<User> userList = userMapper.selectList(queryWrapper);
for (User user : userList) {
System.out.println(user);
}
}
/**
* 使用条件构造器进行查询
* <p>
* 需求:
* 名字中包含"雨",并且年龄大于等于20,且小于等于40,并且email不为空
* sql: name like '%雨%' and age between 20 and 40 and email is not null
*/
@Test
public void selectByWrapper2() {
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper
//模糊查询,注意这里的字段都是数据库字段,而不是实体的变量名
.like("name", "雨")
//年龄大于20,并且小于40
.between("age", 20, 40)
//不为null
.isNotNull("email");
List<User> userList = userMapper.selectList(queryWrapper);
for (User user : userList) {
System.out.println(user);
}
}
/**
* 使用条件构造器进行查询
* <p>
* 需求:
* 名字为王姓,或者年龄大于等于25,按照年龄降序排列,年龄相同按照id升序排列
* name like '王%' or age>=25 order by age desc,id asc
*/
@Test
public void selectByWrapper3() {
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper
//模糊查询,只包含右边一个%,注意这里的字段都是数据库字段,而不是实体的变量名
.likeRight("name", "王")
.or()
//年龄大于等于25
.ge("age", 25)
//先按年龄降序排(从大到小)
.orderByDesc("age")
//年龄相同的,再按id的升序排(从小到大)
.orderByAsc("id");
List<User> userList = userMapper.selectList(queryWrapper);
for (User user : userList) {
System.out.println(user);
}
}
/**
* 使用条件构造器进行查询
* <p>
* 创建日期为2019年2月14日,并且直属上级为名字为王姓
* sql: date_format(create_time,'%Y-%m-%d')='2019-02-14' and manager_id in (select id from user where name like '王%')
*/
@Test
public void selectByWrapper4() {
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper
//直接用,不使用占位符,可能会有sql注入的风险
//.apply("date_format(create_time,'%Y-%m-%d')=2019-02-14")
//apply占位符查询,目的是为了防止sql注入
.apply("date_format(create_time,'%Y-%m-%d')={0}", "2019-02-14")
//inSql子查询
.inSql("manager_id", "select id from mp_user where name like '王%'");
List<User> userList = userMapper.selectList(queryWrapper);
for (User user : userList) {
System.out.println(user);
}
}
/**
* 使用条件构造器进行查询
* <p>
* 名字为王姓并且(年龄小于40或邮箱不为空)
* sql: name like '王%' and (age<40 or email is not null)
*/
@Test
public void selectByWrapper5() {
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.likeRight("name", "王")
//函数式编程
//.and(wrapper-> wrapper.lt("age", 40).or().isNotNull("email"))
.and(new Function<QueryWrapper<User>, QueryWrapper<User>>() {
@Override
public QueryWrapper<User> apply(QueryWrapper<User> wrapper) {
//年龄小于40
return wrapper.lt("age", 40)
//或者邮箱不为空
.or()
.isNotNull("email");
}
});
List<User> userList = userMapper.selectList(queryWrapper);
for (User user : userList) {
System.out.println(user);
}
}
/**
* 使用条件构造器进行查询
* <p>
* 名字为王姓,或者(年龄小于40并且年龄大于20并且邮箱不为空)
* sql: name like '王%' or (age<40 and age>20 and email is not null)
*/
@Test
public void selectByWrapper6() {
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper
//王姓开头
.likeRight("name", "王")
//or()使用Function参数的,将获取年龄小于40,并且年龄大于20
.or(wrapper -> wrapper.lt("age", 40)
.gt("age", 20)
//并且邮箱不为空的条件用括号包裹起来
.isNotNull("email"));
List<User> userList = userMapper.selectList(queryWrapper);
for (User user : userList) {
System.out.println(user);
}
}
/**
* 使用条件构造器进行查询
* <p>
* (年龄小于40或邮箱不为空)并且名字为王姓
* sql: (age<40 or email is not null) and name like '王%'
*/
@Test
public void selectByWrapper7() {
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper
//nested(),嵌套,就是加括号
.nested(wrapper -> wrapper.lt("age", 40).or().isNotNull("email"))
//邮箱不为null
.likeRight("name", "王");
List<User> userList = userMapper.selectList(queryWrapper);
for (User user : userList) {
System.out.println(user);
}
}
/**
* 使用条件构造器进行查询
* <p>
* 年龄为30、31、34、35
* sql: age in (30、31、34、35)
*/
@Test
public void selectByWrapper8() {
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper
.in("age", Arrays.asList(30, 31, 34, 35));
List<User> userList = userMapper.selectList(queryWrapper);
for (User user : userList) {
System.out.println(user);
}
}
/**
* 使用条件构造器进行查询
* <p>
* 9、只返回满足条件的其中一条语句即可
* sql: limit 1
*/
@Test
public void selectByWrapper9() {
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
//字符串拼接到sql,会有sql注入的风险
queryWrapper.last("limit 1");
List<User> userList = userMapper.selectList(queryWrapper);
for (User user : userList) {
System.out.println(user);
}
}
/**
* 使用条件构造器进行查询
* <p>
* 需求:
* select中字段不全部出现的查询,例如只查询出id和姓名(默认会查询出实体中的所有字段)
* sql: select id,name from user where name like '%雨%' and age<40
*/
@Test
public void selectByWrapperSupper() {
//直接创建一个条件构造器,获取使用Wrappers工具类
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
//QueryWrapper<User> queryWrapper = Wrappers.query();
queryWrapper
//<重点>,相比上面的selectByWrapper,多了调用select()方法,传入需要查询的列名
.select("id", "name")
//模糊查询,注意这里的字段都是数据库字段,而不是实体的变量名
.like("name", "雨")
//小于
.lt("age", 40);
List<User> userList = userMapper.selectList(queryWrapper);
for (User user : userList) {
System.out.println(user);
}
}
/**
* 使用条件构造器进行查询
* <p>
* 需求:
* select中字段不全部出现的查询,例如只查询出id和姓名、年龄、邮箱(默认会查询出实体中的所有字段)
* sql: select id,name,age,email from user where name like '%雨%' and age<40
*/
@Test
public void selectByWrapperSupper2() {
//直接创建一个条件构造器,获取使用Wrappers工具类
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
//QueryWrapper<User> queryWrapper = Wrappers.query();
queryWrapper
//模糊查询,注意这里的字段都是数据库字段,而不是实体的变量名
.like("name", "雨")
//小于
.lt("age", 40)
//如果字段比较多,我们每个都写上会比较麻烦,我们可以使用排除法,毕竟只是去掉少量的字段,其他字段都保留
//参数一:实体类的Class
//参数二:Predicate函数式接口,test()方法返回boolean,表示是否保留当前遍历到的字段,返回true代表需要,false代表不需要
.select(User.class, info -> !info.getColumn().equals("create_time")
&& !info.getColumn().equals("manager_id"));
List<User> userList = userMapper.selectList(queryWrapper);
for (User user : userList) {
System.out.println(user);
}
}
/**
* 测试动态条件
*/
@Test
public void testCondition() {
String name = "王";
String email = "";
condition(name, email);
}
/**
* 查询条件,条件可传可不传
*
* @param name 姓名
* @param email 邮箱
*/
private void condition(String name, String email) {
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
//手动判空后,加入条件
// if (StringUtils.isNotEmpty(name)) {
// queryWrapper.like("name", name);
// }
// if (StringUtils.isNotEmpty(email)) {
// queryWrapper.like("email", email);
// }
//上面不够优雅,代码量大
queryWrapper.like(StringUtils.isNotEmpty(name), "name", name)
.like(StringUtils.isNotEmpty(email), "email", email);
List<User> userList = userMapper.selectList(queryWrapper);
for (User user : userList) {
System.out.println(user);
}
}
/**
* 使用实体Entity中的字段作为查询条件
*/
@Test
public void selectByWrapperEntity() {
//使用实体作为查询条件加入到where中
User whereUser = new User();
whereUser.setReadName("刘雨红");
whereUser.setAge(32);
QueryWrapper<User> queryWrapper = new QueryWrapper<>(whereUser);
//再给查询条件加like等操作也是可以的
queryWrapper
.like("name", "雨")
.lt("age", 40);
List<User> userList = userMapper.selectList(queryWrapper);
for (User result : userList) {
System.out.println(result);
}
}
/**
* 使用map作为sql的查询条件,map中的所有非空属性会作为sql的等于条件来拼接
*/
@Test
public void selectByWrapperAllEq() {
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
Map<String, Object> params = new HashMap<>();
params.put("name", "王天风");
//age参数,如果为null,会给生成的sql加上age is null,如果想过滤掉为null的属性字段,则将allEq的null2IsNull属性设置为false,默认为true
params.put("age", null);
//queryWrapper.allEq(params, false);
//函数式方式,传入BiPredicate过滤器,test()方法返回当前遍历到的键值对是否加入到条件中,返回true表示加入条件中,返回false代表不加入到条件中
queryWrapper.allEq(new BiPredicate<String, Object>() {
@Override
public boolean test(String key, Object value) {
//例如过滤掉name的字段
return !key.equals("name");
}
}, params);
List<User> userList = userMapper.selectList(queryWrapper);
for (User result : userList) {
System.out.println(result);
}
}
/**
* 查询,返回列表,但列表里面的元素不是实体,而是一个Map,每个Map就是一条记录的所有属性以键值对的形式存在
* 当我们查询的字段相比实体字段少很多的时候,使用实体去存放,会有很多属性是null,不是很优雅,我们使用Map存放会更加明确有什么属性和值
*/
@Test
public void selectByWrapperMaps() {
//直接创建一个条件构造器,获取使用Wrappers工具类
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
//QueryWrapper<User> queryWrapper = Wrappers.query();
queryWrapper
.select("id", "name")
//模糊查询,注意这里的字段都是数据库字段,而不是实体的变量名
.like("name", "雨")
//小于
.lt("age", 40);
List<Map<String, Object>> userList = userMapper.selectMaps(queryWrapper);
for (Map<String, Object> map : userList) {
System.out.println(map);
}
}
/**
* 按照直属上级分组,查询每组的平均年龄、最大年龄、最小年龄。并且只取年龄总和小于500的组。
* sql:
* select avg(age) avg_age,min(age) min_age,max(age) max_age
* from user
* group by manager_id
* having sum(age) <500
*/
@Test
public void selectByWrapperMaps2() {
//直接创建一个条件构造器,获取使用Wrappers工具类
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
//QueryWrapper<User> queryWrapper = Wrappers.query();
queryWrapper
//字段起别名:数据库字段名 别名
.select("avg(age) avg_age", "min(age) min_age", "max(age) max_age")
.groupBy("manager_id").having("sum(age) < {0}", 500);
List<Map<String, Object>> userList = userMapper.selectMaps(queryWrapper);
for (Map<String, Object> map : userList) {
System.out.println(map);
}
}
/**
* selectObjs(),只拿出数据的第一列的数据,其他列都被舍弃(sql中是会查询其他字段的,但是selectObjs()方法只选择第一列的数据)
* 场景:只返回第一列的时候可以用它
*/
@Test
public void selectByWrapperObjs() {
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper
.select("id", "name")
//模糊查询,注意这里的字段都是数据库字段,而不是实体的变量名
.like("name", "雨")
//小于
.lt("age", 40);
List<Object> userList = userMapper.selectObjs(queryWrapper);
for (Object o : userList) {
System.out.println(o);
}
}
/**
* 统计查询
*/
@Test
public void selectByWrapperCount() {
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper
//会帮我们在sql中添加 COUNT( 1 ),所以我们就不能使用select()方法来指定要查询的列了,否则会作为count的参数来使用
//.select("id", "name")
//除非你想count其他字段,就可以使用
.select("id")
//模糊查询,注意这里的字段都是数据库字段,而不是实体的变量名
.like("name", "雨")
//小于
.lt("age", 40);
Integer count = userMapper.selectCount(queryWrapper);
System.out.println("count:" + count);
}
/**
* 只查询出1条数据(必须查询结果只有1条,多条会报错)
*/
@Test
public void selectByWrapperOne() {
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper
.select("id", "name")
//模糊查询,注意这里的字段都是数据库字段,而不是实体的变量名
.eq("name", "刘雨红");
User user = userMapper.selectOne(queryWrapper);
System.out.println(user);
}
/**
* Lambda条件构造器
* 好处:仿误写,如果是普通方式,传入数据库字段名,如果写错了就会报错,Lambda表达式使用方法引用来获取字段信息
*/
@Test
public void selectByWrapperLambda() {
//Lambda条件构造器的3种创建方式
// LambdaQueryWrapper<User> queryWrapper = new QueryWrapper<User>().lambda();
// LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
LambdaQueryWrapper<User> queryWrapper = Wrappers.lambdaQuery();
queryWrapper
//where name like '%雨%'
.like(User::getReadName, "雨")
//and age < 40
.lt(User::getAge, 40);
List<User> userList = userMapper.selectList(queryWrapper);
for (User user : userList) {
System.out.println(user);
}
}
/**
* 查询,姓名为王姓,并且(年龄小于40岁或者邮箱不为空)
*/
@Test
public void selectByWrapperLambda2() {
LambdaQueryWrapper<User> queryWrapper = Wrappers.lambdaQuery();
queryWrapper
//where name like '%王%'
.likeRight(User::getReadName, "王")
//and (age < 40 or email is not null)
.and(lqw -> lqw.lt(User::getAge, 40).or().isNotNull(User::getEmail));
List<User> userList = userMapper.selectList(queryWrapper);
for (User user : userList) {
System.out.println(user);
}
}
/**
* 查询,姓名为王姓,并且年龄大于等于20
*/
@Test
public void selectByWrapperLambda3() {
LambdaQueryChainWrapper<User> chainWrapper = new LambdaQueryChainWrapper<>(userMapper);
List<User> userList = chainWrapper
//姓名为王姓
.like(User::getReadName, "雨")
//年龄大于等于20
.ge(User::getAge, 20)
.list();
for (User user : userList) {
System.out.println(user);
}
}
}
- Пейджинговый запрос
BaseMapper также предоставляет связанные методы для запросов пейджинга.
- selectPage, передать объект страницы параметра подкачки и условный конструктор QueryWrapper, вернуть объект IPage, и есть параметры подкачки, такие как общее количество страниц и общее количество записей в IPage.
- selectMapsPage, второй метод пейджинга, общий тип объекта пейджинга — Map, а не объект класса сущностей, то есть поля и значения класса сущностей инкапсулированы в Map
- selectPage, входящий объект пейджинга, конструктор настраивает для параметра isSearchCount значение false, что означает пейджинг, но не запрашивает общее количество записей. В сценариях, где общее количество записей не требуется, один запрос можно уменьшить, например со стороны приложения загружать больше не нужно.Общее количество записей необходимо оценивать
/**
* 分页查询,分页对象的泛型是实体类
*/
@Test
public void selectPage() {
//直接创建一个条件构造器,获取使用Wrappers工具类
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.ge("age", 26);
Page<User> page = new Page<>(1, 2);
//分页
IPage<User> iPage = userMapper.selectPage(page, queryWrapper);
System.out.println("总页数:" + iPage.getPages());
System.out.println("总记录数:" + iPage.getTotal());
List<User> userList = iPage.getRecords();
for (User user : userList) {
System.out.println(user);
}
}
/**
* 第二种分页方式,分页对象的泛型是Map
*/
@Test
public void selectPage2() {
//直接创建一个条件构造器,获取使用Wrappers工具类
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.ge("age", 26);
Page<User> page = new Page<>(1, 2);
//第二种分页,但返回的IPage泛型类型是Map类型,就是将实体类的字段和值封装到了Map中
IPage<Map<String, Object>> iPage = userMapper.selectMapsPage(page, queryWrapper);
System.out.println("总页数:" + iPage.getPages());
System.out.println("总记录数:" + iPage.getTotal());
List<Map<String, Object>> userList = iPage.getRecords();
for (Map<String, Object> map : userList) {
System.out.println(map);
}
}
/**
* 分页,不查询总记录数(默认会查,会查询总数和分页查询,会查询2次,例如不断上拉加载的场景是不需要查总记录数的,就可以不进行查询)
*/
@Test
public void selectPage3() {
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.ge("age", 26);
//isSearchCount传false,代表不进行查询总记录数,少一次查询
Page<User> page = new Page<>(1, 2, false);
//分页
IPage<User> iPage = userMapper.selectPage(page, queryWrapper);
System.out.println("总页数:" + iPage.getPages());
List<User> userList = iPage.getRecords();
for (User user : userList) {
System.out.println(user);
}
}
Пользовательский метод сопоставления
Предоставьте собственный метод Mapper
Добавьте 2 пользовательских метода в UserMapper.
Есть два способа настройки метода, аннотация и XML.Здесь в основном используется XML, но также предоставляется аннотация.Поскольку они не могут существовать одновременно, они закомментированы.При необходимости вы можете обратиться к нему снова.
- selectAll, пользовательские параметры запроса, условия запроса предоставляются входящей оболочкой, параметры должны быть аннотированы с помощью @Param, а имена параметров фиксированы, как Constants.WRAPPER
- selectUserPage, настраиваемые параметры запроса с функцией подкачки, необходимо передать 2 параметра, объект Page и объект Wrapper, один и тот же параметр должен быть аннотирован с помощью @Param, а имя параметра фиксировано, оба параметра Constants.WRAPPER
public interface UserMapper extends BaseMapper<User> {
/**
* 自定义Sql查询,让Wrapper中配置的条件和自定义sql进行组合
*/
//@Select("select * from mp_user ${ew.customSqlSegment}")
List<User> selectAll(@Param(Constants.WRAPPER) Wrapper<User> wrapper);
/**
* 自定义Sql,进行分页查询
*/
IPage<User> selectUserPage(Page<User> page, @Param(Constants.WRAPPER) Wrapper<User> wrapper);
}
XML-файл для настройки Mapper
Существуют настраиваемые интерфейсы Mapper, использующие либо аннотации, либо XML, обычно использующие XML. В каталоге ресурсов создайте многослойную папку com/imooc/mybatisplus.mapper и создайте в ней новый файл XML: UserMapper.xml
Примечание. Имя интерфейса Mapper и соответствующего XML-файла должны совпадать! а пространство имен — это полное имя класса Mapper
<?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">
<!-- namespace,命名空间必须和Dao接口一样 -->
<mapper namespace="com.imooc.mybatisplus.dao.UserMapper">
<!-- 查询所有 -->
<select id="selectAll" resultType="User">
select * from mp_user ${ew.customSqlSegment}
</select>
<!-- 分页查询 -->
<select id="selectUserPage" resultType="User">
select * from mp_user ${ew.customSqlSegment}
</select>
</mapper>
Способы тестирования пользовательского SQL
Условия настраиваются в экземпляре Wrapper, а запрашиваемые поля предоставляются пользовательскими операторами SQL.
Это запросы selectAll() all и selectMyPage() соответственно.
/**
* 自定义sql
*/
@Test
public void selectMy() {
LambdaQueryWrapper<User> lambdaQuery = Wrappers.lambdaQuery();
lambdaQuery
//where name like '%王%'
.likeRight(User::getReadName, "王")
//and (age < 40 or email is not null)
.and(lqw -> lqw.lt(User::getAge, 40).or().isNotNull(User::getEmail));
List<User> userList = userMapper.selectAll(lambdaQuery);
for (User user : userList) {
System.out.println(user);
}
}
/**
* 自定义查询分页
*/
@Test
public void selectMyPage() {
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.ge("age", 26);
Page<User> page = new Page<>(1, 2);
//自定义分页查询
IPage<User> iPage = userMapper.selectUserPage(page, queryWrapper);
System.out.println("总页数:" + iPage.getPages());
System.out.println("总记录数:" + iPage.getTotal());
List<User> userList = iPage.getRecords();
for (User user : userList) {
System.out.println(user);
}
}
Общего обслуживания
Мы использовали общий Mapper выше, и, как правило, у нас будет служба, которая объединяет несколько Mapper для завершения бизнес-логики.
MyBatis-Plus также предоставляет нам общее сервисное решение.
Установить интерфейс службы и реализацию
Создайте пакет службы, интерфейс UserService, наследуйте интерфейс IService и в общем запишите тип класса сущности.
public interface UserService extends IService<User> {
}
Создайте класс реализации UserServiceImpl, наследуйте ServiceImpl, в общем случае передайте интерфейс Mapper и тип класса сущности
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
}
контрольная работа
- getOne, получить 1 результат, если будет несколько результатов, будет сообщено об ошибке. Если вы не хотите сообщать об ошибке, возьмите первую по умолчанию, а затем установите для последующего свойства throwEx значение false.
- saveBatch, сохраняет несколько объектов в таблицу базы данных, если поле id объекта объекта имеет значение, оно обновляется, если оно равно нулю, значит новое
- lambdaQuery, список вызовов, запрос цепного программирования
- lambdaUpdate, обновление вызова, обновление цепного программирования
- lambdaUpdate, удаление вызова, удаление цепного программирования
@RunWith(SpringRunner.class)
@SpringBootTest(classes = Application.class)
public class ServiceTest {
@Autowired
private UserService userService;
/**
* 获取一个结果
*/
@Test
public void getOne() {
//查询1个,如果有多个结果,会报错。
//后面的throwEx属性代表如果查询出多个,是否抛出异常,默认为true,如果有多个就抛出异常
//如果设置为false,则不抛出异常,打印警告,并且拿取第一个返回
User result = userService.getOne(Wrappers.<User>lambdaQuery()
.gt(User::getAge, 25), false);
System.out.println(result);
}
/**
* 批量插入
*/
@Test
public void batch() {
User user1 = new User();
user1.setReadName("徐丽1");
user1.setAge(28);
User user2 = new User();
user2.setReadName("徐丽2");
user2.setAge(29);
List<User> userList = Arrays.asList(user1, user2);
boolean isSuccess = userService.saveBatch(userList);
System.out.println("是否批量插入成功:" + isSuccess);
}
/**
* 批量操作,如果设置了id,则先查询,有则更新,无则做插入
*/
@Test
public void batch2() {
User user1 = new User();
user1.setReadName("徐丽3");
user1.setAge(28);
User user2 = new User();
user2.setUserId(1289004540795330562L);
user2.setReadName("徐力");
user2.setAge(30);
List<User> userList = Arrays.asList(user1, user2);
boolean isSuccess = userService.saveOrUpdateBatch(userList);
System.out.println("是否批量插入成功:" + isSuccess);
}
/**
* 链式编程,查询
*/
@Test
public void chain() {
List<User> userList = userService.lambdaQuery()
.gt(User::getAge, 25)
.like(User::getReadName, "雨")
.list();
for (User user : userList) {
System.out.println(user);
}
}
/**
* 链式编程,更新
*/
@Test
public void chain2() {
boolean isSuccess = userService.lambdaUpdate()
.eq(User::getAge, 25)
.set(User::getAge, 26)
.update();
System.out.println("是否更新成功:" + isSuccess);
}
/**
* 链式编程,删除
*/
@Test
public void chain3() {
boolean isSuccess = userService.lambdaUpdate()
.eq(User::getAge, 24)
.remove();
System.out.println("是否删除成功:" + isSuccess);
}
}
режим дополненной реальности
Режим AR, то есть режим ActiveRecord, использует операции класса сущностей для добавления, удаления, проверки и изменения, а классы сущностей необходимо модифицировать.
- Класс сущностей наследует класс Model, а универсальный тип переходит в тип класса сущностей.
- Создать сериализованный UID
@Data
@EqualsAndHashCode(callSuper = false)
@TableName("mp_user")
public class User extends Model<User> {
private static final long serialVersionUID = 1L;
//...省略字段,和之前的没区别
}
контрольная работа
- вставить, вставить данные
- selectById, основанный на запросе первичного ключа сущности, также может передаваться в параметрах метода.
- updateById, обновить набор данных объекта в соответствии с первичным ключом объекта.
- deleteById, удаление в соответствии с первичным ключом объекта, также может передаваться в параметре метода
- insertOrUpdate, новое или обновленное, в зависимости от того, имеет ли первичный ключ объекта значение, если есть значение, оно обновляется, а если оно равно null, оно новое
@RunWith(SpringRunner.class)
@SpringBootTest(classes = Application.class)
public class ARTest {
/**
* 插入数据
*/
@Test
public void insert() {
User user = new User();
user.setReadName("刘花");
user.setAge(29);
user.setEmail("lh@baomidou.com");
user.setManagerId(1088248166370832385L);
user.setCreateTime(LocalDateTime.now());
boolean isSuccess = user.insert();
System.out.println("是否插入成功:" + isSuccess);
}
/**
* 按主键进行查询
*/
@Test
public void selectById() {
User user = new User();
User result = user.selectById(1288460195017072641L);
System.out.println(result);
}
/**
* 按实体类上的主键属性进行查询
*/
@Test
public void selectById2() {
User user = new User();
user.setUserId(1288839790966910978L);
User result = user.selectById();
System.out.println(result);
}
/**
* 更新,按实体类上的主键属性
*/
@Test
public void updateById() {
User user = new User();
user.setUserId(1288839790966910978L);
user.setReadName("刘草");
boolean isSuccess = user.updateById();
System.out.println("是否更新成功:" + isSuccess);
}
/**
* 按主键删除
*/
@Test
public void deleteById() {
User user = new User();
boolean isSuccess = user.deleteById(1288839790966910978L);
System.out.println("是否删除成功:" + isSuccess);
}
/**
* 按实体类上的主键属性进行删除
*/
@Test
public void deleteById2() {
User user = new User();
user.setUserId(1288839790966910978L);
boolean isSuccess = user.deleteById();
System.out.println("是否删除成功:" + isSuccess);
}
/**
* 先查询主键Id的记录,如果有则更新,无则新增
*/
@Test
public void insertOrUpdate() {
User user = new User();
//设置了主键Id,则会先查询,有记录则更新,无则删除
//user.setUserId(1288842439342780417L);
user.setReadName("张强");
user.setAge(29);
user.setEmail("lh@baomidou.com");
user.setManagerId(1088248166370832385L);
user.setCreateTime(LocalDateTime.now());
boolean isSuccess = user.insertOrUpdate();
System.out.println("是否插入成功:" + isSuccess);
}
}