会当凌绝顶,一览众山小
| @Author:TTODS
MyBatisPlus框架系列文章目录:
-
MyBatisPlus Service层的CRUD(当前)
-
[MyBatisPlus之代码生成器(近期发布)]
前言
与Mapper层类似,MybatisPlus也提供了具有通用CRUD功能的Service层接口.本文将介绍如何使用MybatisPlus提供的基类与接口构建我们的Service层,以及如何使用Service层的通用CRUD.
创建UserService接口
在包com.example.service
中创建一个UserService
接口,并使其继承mybatis-plus提供的IService<T>
接口(T
表示对应实体类类型)。
package com.example.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.example.pojo.User;
public interface UserService extends IService<User> {
}
创建UserServiceImpl类
在包com.example.service.impl
中创建一个UserServiceImpl类,并使其继承mybatis-plus提供的ServiceImpl<M extends BaseMapper<T>, T>
类(T表示对应实体类类型),并实现上一步中创建的UserService
接口。然后加上@Service
注解。
package com.example.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.mapper.UserMapper;
import com.example.pojo.User;
import com.example.service.UserService;
import org.springframework.stereotype.Service;
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
}
创建好之后项目结构如下:
至此,虽然我们没有在UserService
中内写任何代码,但它已经具备了mybatis-plus提供的基本的CRUD的功能。
Service层的CRUD
save方法
boolean save(T entity); // 插入一条记录
boolean saveBatch(Collection<T> entityList);// 插入(批量),默认分批大小为1000
boolean saveBatch(Collection<T> entityList, int batchSize);// 插入(批量)
public class ServiceCurdTests {
@Autowired
UserService userService;
@Test
public void testSave(){
// 创建实体类对象
User user = new User();
user.setName("Garrison");
user.setAge(45);
user.setEmail("garrsion@gmail.com");
user.setGender(1);
// 调用save方法
userService.save(user);
}
}
生成的sql语句及输出:
==> Preparing: INSERT INTO user ( name, age, gender, email ) VALUES ( ?, ?, ?, ? )
==> Parameters: Garrison(String), 45(Integer), 1(Integer), garrsion@gmail.com(String)
<== Updates: 1
查看数据库,修改成功。
saveOrUpdate方法
boolean saveOrUpdate(T entity); // TableId 注解存在更新记录,否插入一条记录
boolean saveOrUpdate(T entity, Wrapper<T> updateWrapper);// 根据updateWrapper尝试更新,否继续执行saveOrUpdate(T)方法
boolean saveOrUpdateBatch(Collection<T> entityList);// 批量修改插入
boolean saveOrUpdateBatch(Collection<T> entityList, int batchSize);// 批量修改插入
saveOrUpdate测试1:
@Test
public void testSaveOrUpdate(){
User user = new User();
user.setId(7);
user.setAge(1);
userService.saveOrUpdate(user);
}
生成的Sql代码:
==> Preparing: SELECT id,name,age,gender,email FROM user WHERE id=?
==> Parameters: 7(Integer)
<== Total: 1
==> Preparing: UPDATE user SET age=? WHERE id=?
==> Parameters: 1(Integer), 7(Integer)
<== Updates: 1
saveOrUpdate测试2:
@Test
public void testSaveOrUpdate1(){
User user = new User();
user.setId(8);
user.setAge(1);
userService.saveOrUpdate(user);
}
生成的sql代码:
==> Preparing: SELECT id,name,age,gender,email FROM user WHERE id=?
==> Parameters: 8(Integer)
<== Total: 0
==> Preparing: INSERT INTO user ( age ) VALUES ( ? )
==> Parameters: 1(Integer)
<== Updates: 1
通过上面两个测试可以看出:updateOrSave方法会先运行一个Select
语句,通过主键字段判断该条记录是否存在,若存在则运行Update
语句,否则运行Insert
语句,且实体类中为null的属性,不会更新。
remove方法
boolean remove(Wrapper<T> queryWrapper);// 根据 entity 条件,删除记录
boolean removeById(Serializable id); // 根据 ID 删除
boolean removeByMap(Map<String, Object> columnMap);// 根据 columnMap 条件,删除记录
boolean removeByIds(Collection<? extends Serializable> idList);// 删除(根据ID 批量删除)
update方法
boolean update(Wrapper<T> updateWrapper);// 根据 UpdateWrapper 条件,更新记录 需要设置sqlset
boolean update(T updateEntity, Wrapper<T> whereWrapper);// 根据 whereWrapper 条件,更新记录
boolean updateById(T entity);// 根据 ID 选择修改
boolean updateBatchById(Collection<T> entityList);// 根据ID 批量更新
boolean updateBatchById(Collection<T> entityList, int batchSize);// 根据ID 批量更新
@Test
public void update(){
User user = new User();
user.setName("Hailie");
user.setAge(32);
user.setGender(0);
user.setEmail("haile@gmail.com");
// 第一个参数实体类对象中的值将会生成对应的set子句
userService.update(user,new UpdateWrapper<User>().eq("id",8));
}
生成的sql:
==> Preparing: UPDATE user SET name=?, age=?, gender=?, email=? WHERE (id = ?)
==> Parameters: Hailie(String), 32(Integer), 0(Integer), haile@gmail.com(String), 8(Integer)
<== Updates: 1
查看数据库,修改成功。
一个奇奇怪怪的问题
假设我们使用boolean update(T updateEntity, Wrapper<T> whereWrapper)
方法时,在第二个参数中使用UpdateWrappper且设置set与第一个实体类对象中参数冲突会怎么样呢?
本例只是本人学习过程中的突发奇想[doge]…高危代码…请勿模仿…[doge]
@Test
public void update01(){
User user = new User();
//在此设置年龄为30
user.setAge(30);
// 在第二个参数中设置年龄为29
userService.update(user,new UpdateWrapper<User>().eq("id",8).set("age",29));
}
生成的sql代码:
==> Preparing: UPDATE user SET age=?, age=? WHERE (id = ?)
==> Parameters: 30(Integer), 29(Integer), 8(Integer)
<== Updates: 1
还是可以成功运行,不过生成的sql语句中age被设置了两次,由于age=29在后面,所以最后数据库中的结果是29.
Get方法
根据条件查询一条记录
T getById(Serializable id);// 根据 ID 查询
T getOne(Wrapper<T> queryWrapper);// 根据 Wrapper,查询一条记录。结果集,如果是多个会抛出异常,随机取一条加上限制条件 wrapper.last("LIMIT 1")
T getOne(Wrapper<T> queryWrapper, boolean throwEx);// 根据 Wrapper,查询一条记录
Map<String, Object> getMap(Wrapper<T> queryWrapper);// 根据 Wrapper,查询一条记录
<V> V getObj(Wrapper<T> queryWrapper, Function<? super Object, V> mapper);// 根据 Wrapper,查询一条记录
List方法
根据条件查询多条记录
List<T> list();// 查询所有
List<T> list(Wrapper<T> queryWrapper);// 查询列表
Collection<T> listByIds(Collection<? extends Serializable> idList);// 查询(根据ID 批量查询)
Collection<T> listByMap(Map<String, Object> columnMap);// 查询(根据 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);// 根据 Wrapper 条件,查询全部记录
<V> List<V> listObjs(Wrapper<T> queryWrapper, Function<? super Object, V> mapper);// 根据 Wrapper 条件,查询全部记录
Page方法
请阅读~~<<mybatis-plus分页功能>>~~
Count方法
int count();// 查询总记录数
int count(Wrapper<T> queryWrapper);// 根据 Wrapper 条件,查询总记录数
@Test
public void testCount(){
int total = userService.count();
int male = userService.count(new QueryWrapper<User>().eq("gender",1));
int female = userService.count(new QueryWrapper<User>().eq("gender", 0));
System.out.println(String.format("用户总数: %d\n其中:\n\t男性:\t%d\n\t女性:\t%d",
total,male,female));
}
生成的sql语句及输出
==> Preparing: SELECT COUNT( 1 ) FROM user WHERE (gender = ?)
==> Parameters: 0(Integer)
<== Total: 1
用户总数: 8
其中:
男性: 5
女性: 3
链式查询与链式更新
@Test
public void testChainQuery(){
QueryChainWrapper<User> query = new QueryChainWrapper<>(userMapper);
// 查询所有男性用户的id、name和age
List<User> users = query.select("id", "name", "age").eq("gender",0).list();
for (User user : users) {
System.out.println(user);
}
}
生成的sql语句及输出:
@Test
public void testChainUpdate(){
UpdateChainWrapper<User> query = new UpdateChainWrapper<>(userMapper);
// 使所有女性用户年龄增加1
query.setSql("age = age+1").eq("gender",1).update();
}
生成的sql语句:
==> Preparing: UPDATE user SET age = age+1 WHERE (gender = ?)
==> Parameters: 1(Integer)
<== Updates: 5
上一篇:MyBatisPlus Mapper层的CRUD
下一篇:MyBatisPlus提供的分页功能