该笔记来自B站SGG-MyBatisPlus学习记录及MP官网,文章没多少干货,只是作一次学习记录
2022.10.18
架构示意

依赖(基于SpringBoot+Mysql)
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.1</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
</dependencies>
数据源配置
spring:
datasource:
type: com.zaxxer.hikari.HikariDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/mybatis_plus?characterEncoding=utf-
8&useSSL=false
username: root
password: 123456
1. 关于driver-class-name驱动配置项(看SpringBoot版本)
spring boot 2.0(内置jdbc5驱动),驱动类使用:
driver-class-name: com.mysql.jdbc.Driver
spring boot 2.1及以上(内置jdbc8驱动),驱动类使用:
driver-class-name: com.mysql.cj.jdbc.Driver
2. 连接地址(看Mysql版本等数据库)
MySQL5.7版本的url:
jdbc:mysql://localhost:3306/mybatis_plus?characterEncoding=utf-8&useSSL=false
MySQL8.0版本的url:
jdbc:mysql://localhost:3306/mybatis_plus?
serverTimezone=GMT%2B8&characterEncoding=utf-8&useSSL=false
启动类(或配置类)上配置mapper包扫描地址
@SpringBootApplication
@MapperScan("com.test.mybatisplus.mapper")
public class MybatisplusApplication {
public static void main(String[] args) {
SpringApplication.run(MybatisplusApplication.class, args);
}
}
库表结构及数据
CREATE DATABASE `mybatis_plus` /*!40100 DEFAULT CHARACTER SET utf8mb4 */;
use `mybatis_plus`;
CREATE TABLE `user` (
`id` bigint(20) NOT NULL COMMENT '主键ID',
`name` varchar(30) DEFAULT NULL COMMENT '姓名',
`age` int(11) DEFAULT NULL COMMENT '年龄',
`email` varchar(50) DEFAULT NULL COMMENT '邮箱',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO user (id, name, age, email) VALUES
(1, 'Jone', 18, 'test1@baomidou.com'),
(2, 'Jack', 20, 'test2@baomidou.com'),
(3, 'Tom', 28, 'test3@baomidou.com'),
(4, 'Sandy', 21, 'test4@baomidou.com'),
(5, 'Billie', 24, 'test5@baomidou.com');
通用Mapper
通用Mapper就是在我们可以使用MyBatisPlus提供的封装好的一些单表的基本的CURD操作,直接在Mapper层(Dao层)与数据库进行交互
首先,我们需要在编写自己的Mapper(或Dao层)接口时,去继承【BaseMapper】
public interface UserMapper extends BaseMapper<User> {
}
其中BaseMapper中的泛型指的是我们的实体类名(一般来说简单的表实体名和表名一致)
@Autowired
private UserMapper userMapper;
1. Insert
int insert(T entity)
@Test
public void testInsert(){
User user = new User(null, "张三", 23, "zhangsan@atguigu.com");
int result = userMapper.insert(user);
System.out.println("受影响行数:"+result);
}
2. Delete
int delete(@Param(Constants.WRAPPER) Wrapper<T> wrapper);
int deleteBatchIds(@Param(Constants.COLLECTION) Collection<? extends Serializable> idList);
@Test
public void testDeleteBatchIds(){
List<Long> idList = Arrays.asList(1L, 2L, 3L);
int result = userMapper.deleteBatchIds(idList);
System.out.println("受影响行数:"+result);
}
int deleteById(Serializable id);
@Test
public void testDeleteById(){
int result = userMapper.deleteById(1475754982694199298L);
System.out.println("受影响行数:"+result);
}
int deleteByMap(@Param(Constants.COLUMN_MAP) Map<String, Object> columnMap);
@Test
public void testDeleteByMap(){
Map<String, Object> map = new HashMap<>();
map.put("age", 23);
map.put("name", "张三");
int result = userMapper.deleteByMap(map);
System.out.println("受影响行数:"+result);
}
3. Update
int update(@Param(Constants.ENTITY) T updateEntity, @Param(Constants.WRAPPER) Wrapper<T> whereWrapper);
int updateById(@Param(Constants.ENTITY) T entity);
@Test
public void testUpdateById(){
User user = new User(4L, "admin", 22, null);
int result = userMapper.updateById(user);
System.out.println("受影响行数:"+result);
}
4. Select
T selectById(Serializable id);
@Test
public void testSelectById(){
User user = userMapper.selectById(4L);
System.out.println(user);
}
T selectOne(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
List<T> selectBatchIds(@Param(Constants.COLLECTION) Collection<? extends Serializable> idList);
@Test
public void testSelectBatchIds(){
List<Long> idList = Arrays.asList(4L, 5L);
List<User> list = userMapper.selectBatchIds(idList);
list.forEach(System.out::println);
}
List<T> selectList(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
@Test
public void testSelectList(){
List<User> list = userMapper.selectList(null);
list.forEach(System.out::println);
}
List<T> selectByMap(@Param(Constants.COLUMN_MAP) Map<String, Object> columnMap);
@Test
public void testSelectByMap(){
Map<String, Object> map = new HashMap<>();
map.put("age", 22);
map.put("name", "admin");
List<User> list = userMapper.selectByMap(map);
list.forEach(System.out::println);
}
List<Map<String, Object>> selectMaps(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
List<Object> selectObjs(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
IPage<T> selectPage(IPage<T> page, @Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
IPage<Map<String, Object>> selectMapsPage(IPage<T> page, @Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
Integer selectCount(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
通用Service
通用Service就是在我们可以使用MyBatisPlus提供的封装好的一些单表的基本的CURD操作,直接在Service层与数据库进行交互
MyBatis-Plus中有一个接口 IService和其实现类 ServiceImpl,封装了常见的业务层逻辑
一般我们都会有自己的业务Service接口,因此我们需要继承MyBatisPlus的ServiceImpl再实现我们自定义的Service接口
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements
UserService {
}
1. Save
boolean save(T entity);
boolean saveBatch(Collection<T> entityList);
@Test
public void testSaveBatch(){
ArrayList<User> users = new ArrayList<>();
for (int i = 0; i < 5; i++) {
User user = new User();
user.setName("ybc" + i);
user.setAge(20 + i);
users.add(user);
}
userService.saveBatch(users);
}
boolean saveBatch(Collection<T> entityList, int batchSize);
2. SaveOrUpdate
boolean saveOrUpdate(T entity);
boolean saveOrUpdate(T entity, Wrapper<T> updateWrapper);
boolean saveOrUpdateBatch(Collection<T> entityList);
boolean saveOrUpdateBatch(Collection<T> entityList, int batchSize);
3. Remove
boolean remove(Wrapper<T> queryWrapper);
boolean removeById(Serializable id);
boolean removeByMap(Map<String, Object> columnMap);
boolean removeByIds(Collection<? extends Serializable> idList);
4. Update
boolean update(Wrapper<T> updateWrapper);
boolean update(T updateEntity, Wrapper<T> whereWrapper);
boolean updateById(T entity);
boolean updateBatchById(Collection<T> entityList);
boolean updateBatchById(Collection<T> entityList, int batchSize);
5. Get
T getById(Serializable id);
T getOne(Wrapper<T> queryWrapper);
T getOne(Wrapper<T> queryWrapper, boolean throwEx);
Map<String, Object> getMap(Wrapper<T> queryWrapper);
<V> V getObj(Wrapper<T> queryWrapper, Function<? super Object, V> mapper);
6. List
List<T> list();
List<T> list(Wrapper<T> queryWrapper);
Collection<T> listByIds(Collection<? extends Serializable> idList);
Collection<T> listByMap(Map<String, Object> columnMap);
List<Map<String, Object>> listMaps();
List<Map<String, Object>> listMaps(Wrapper<T> queryWrapper);
List<Object> listObjs();
<V> List<V> listObjs(Function<? super Object, V> mapper);
List<Object> listObjs(Wrapper<T> queryWrapper);
<V> List<V> listObjs(Wrapper<T> queryWrapper, Function<? super Object, V> mapper);
7. Page
IPage<T> page(IPage<T> page);
IPage<T> page(IPage<T> page, Wrapper<T> queryWrapper);
IPage<Map<String, Object>> pageMaps(IPage<T> page);
IPage<Map<String, Object>> pageMaps(IPage<T> page, Wrapper<T> queryWrapper);
8. Count
int count();
int count(Wrapper<T> queryWrapper);
9. Chain
chain-query
QueryChainWrapper<T> query();
LambdaQueryChainWrapper<T> lambdaQuery();
query().eq("column", value).one();
lambdaQuery().eq(Entity::getId, value).list();
chain-update
UpdateChainWrapper<T> update();
LambdaUpdateChainWrapper<T> lambdaUpdate();
update().eq("column", value).remove();
lambdaUpdate().eq(Entity::getId, value).update(entity);
常用注解
1. @TableName
使用MyBatis-Plus实现基本的CRUD时,我们并没有指定要操作的表,只是在Mapper接口继承BaseMapper时,设置了泛型User,而操作的表为user表,因此MyBatis-Plus在确定操作的表时,由BaseMapper的泛型决定,即实体类型决定,且默认操作的表名和实体类型的类名一致
1.1 若操作的实体与表名不一致时,我们可以使用@TableName来修正
若表名为【t_user】则对应的实体类标识
@TableName("t_user")
public class User{
}
1.2 若团队规定了使用统一方式建表,如t_tablename,则可以通过全局配置解决
mybatis-plus:
configuration:
global-config:
db-config:
# 配置MyBatis-Plus操作表的默认前缀
table-prefix: t_
2. @TableId
MyBatis-Plus在实现CRUD时,会默认将id作为主键列,并在插入数据时,默认基于雪花算法的策略生成id,若我们表、实体类中主键名称非id,即使我们在表中让主键自增,而不设置实体主键标识,同样在使用MP时不会生效;若我们的表中主键与实体主键属性不一致时,我们需要通过实体类主键属性进行标识
1.1 实体类与表主键名称非【id】
public class User{
@TableId
private Long uid;
}
1.2 实体类与表主键名称不一致
public class User{
@TableId("uid") | @TableId(value="uid")
private Long id;
}
1.3 type属性
IdType.ASSIGN_ID(默认) 基于雪花算法的策略生成数据id,与数据库id是否设置自增无关;
IdType.AUTO 使用数据库的自增策略,注意,该类型请确保数据库设置了id自增,否则无效
@TableId(value="uid", type=IdType.AUTO)
1.4 全局配置
mybatis-plus:
configuration:
global-config:
db-config:
# 配置MyBatis-Plus的主键策略
id-type: auto
3. @TableField
MyBatis-Plus在执行SQL语句时,要保证【实体类中的属性名】和【表中的字段名】一致
1.1 驼峰转换
一般在java实体类中我们使用驼峰命名,而表字段我们使用下划线命名,如userName【user_name】
MyBatis-Plus会自动将下划线命名风格转化为驼峰命名风格,在MyBatis中我们得知此项可设置,而MP则自动转换
1.2 两边不一致
如name【user_name】,此时需要使用@TableField标识
public class User{
@TableField("user_name")
private String name;
}
4. @TableLogic
物理删除:真实删除,将对应数据从数据库中删除,之后查询不到此条被删除的数据
逻辑删除:假删除,将对应数据中代表是否被删除字段的状态修改为“被删除状态”,之后在数据库
中仍旧能看到此条数据记录
1. 实体中增加逻辑删除标识属性
public class User{
@TableLogic
private Integer hasDeleted;
}
2. 表中增加has_deleted字段
条件构造器

配合通用Service、通用Mapper中所提供的方法参数为Wrapper的均可使用
1. QueryWrapper
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.like("username", "a")
.between("age", 20, 30)
.isNotNull("email");
List<User> list = userMapper.selectList(queryWrapper);
list.forEach(System.out::println);
String username = null;
Integer ageBegin = 10;
Integer ageEnd = 24;
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper
.like(StringUtils.isNotBlank(username), "username", "a")
.ge(ageBegin != null, "age", ageBegin)
.le(ageEnd != null, "age", ageEnd);
List<User> users = userMapper.selectList(queryWrapper);
users.forEach(System.out::println);
2. UpdateWrapper
UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();
updateWrapper
.set("age", 18)
.set("email", "user@atguigu.com")
.like("username", "a")
.and(i -> i.gt("age", 20).or().isNull("email"));
int result = userMapper.update(null, updateWrapper);
System.out.println(result);
3. LambdaQueryWrapper
String username = "a";
Integer ageBegin = 10;
Integer ageEnd = 24;
LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper
.like(StringUtils.isNotBlank(username), User::getName, username)
.ge(ageBegin != null, User::getAge, ageBegin)
.le(ageEnd != null, User::getAge, ageEnd);
List<User> users = userMapper.selectList(queryWrapper);
users.forEach(System.out::println);
4. LambdaUpdateWrapper
LambdaUpdateWrapper<User> updateWrapper = new LambdaUpdateWrapper<>();
updateWrapper
.set(User::getAge, 18)
.set(User::getEmail, "user@atguigu.com")
.like(User::getName, "a")
.and(i -> i.lt(User::getAge, 24).or().isNull(User::getEmail));
User user = new User();
int result = userMapper.update(user, updateWrapper);
System.out.println("受影响的行数:" + result);
); List users = userMapper.selectList(queryWrapper); users.forEach(System.out::println);
- LambdaUpdateWrapper
LambdaUpdateWrapper updateWrapper = new LambdaUpdateWrapper<>(); updateWrapper .set(User::getAge, 18) .set(User::getEmail, “user@atguigu.com”) .like(User::getName, “a”) .and(i -> i.lt(User::getAge, 24).or().isNull(User::getEmail)); User user = new User(); int result = userMapper.update(user, updateWrapper); System.out.println(“受影响的行数:” + result);
|