(2)通用的BaseMapper和IService中的CRUD

通用BaseMapper中的CRUD

MyBatis-Plus内置的BaseMapper接口中定义了基本CRUD方法,自定义mapper接口继承的BaseMapper接口中的方法动态生成的代理类都会实现

  • BaseMapper接口中没有批量添加的功能, 因为执行SQL的长度有限制,将海量的添加数据都写到一条SQL语句中会导致其无法执行
package com.baomidou.mybatisplus.core.mapper;
public interface BaseMapper<T> extends Mapper<T> {
    // 插入一条记录
    int insert(T entity);
    
    // 根据entity条件删除记录
    int delete(@Param(Constants.WRAPPER) Wrapper<T> wrapper);
    // 根据id集合批量删除记录,如List idList;
    int deleteBatchIds(idList);
    // 根据ID删除记录
    int deleteById(id);
    // 根据columnMap条件删除记录
    int deleteByMap(@Param(Constants.COLUMN_MAP) Map<String, Object> columnMap);

    // 根据whereEntity条件更新记录
    int update(@Param(Constants.ENTITY) T entity, @Param(Constants.WRAPPER) Wrapper<T> updateWrapper);
    // 根据实体的ID修改
    int updateById(T entity);

    // 根据ID查询
    T selectById(Serializable id);
    // 根据entity条件查询一条记录
    T selectOne(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
    // 根据ID集合批量查询
    List<T> selectBatchIds(@Param(Constants.COLLECTION) Collection<? extends Serializable> idList);
    // 根据entity条件查询记录(参数为null查询所有记录)
    List<T> selectList(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
    // 根据columnMap条件查询
    List<T> selectByMap(@Param(Constants.COLUMN_MAP) Map<String, Object> columnMap);
    // 根据Wrapper条件查询全部记录
    List<Map<String, Object>> selectMaps(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
    // 根据Wrapper条件查询全部记录(返回第一个字段的值)
    List<Object> selectObjs(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);

    // 分页查询
    IPage<T> selectPage(IPage<T> page, @Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
    // 根据Wrapper条件,查询全部记录并翻页
    IPage<Map<String, Object>> selectMapsPage(IPage<T> page, @Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
    // 根据Wrapper条件,查询总记录数
    Integer selectCount(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
}

准备实体类和mapper接口

添加实体类pojo/User封装数据库user表中的数据

@Data //lombok注解
public class User {
    private Long id;
    private String name;
    private Integer age;
    private String email;
}

添加mapper/UserMapper接口继承BaseMapper<操作的实体类型>,在UserMapper接口上添加@Repository注解可以避免IDEA找不到注入对象的问题

  • MyBatis-Plus通过要操作的实体类的类名判断要操作数据库中的哪张表,通过实体类的属性名决定要操作的字段
@Repository
public interface UserMapper extends BaseMapper<User> {
}

在Spring Boot启动类中添加@MapperScan注解扫描指定包下所有的mapper接口, 将这些mapper接口在内存中动态生成的代理对象交给IoC容器管理

  • 自动装配UserMapper时IDEA报错但是程序可以正确的执行: 因为IoC容器管理的mapper接口的代理类是动态创建的所以IDEA找不到注入的对象
@SpringBootApplication
@MapperScan("com.atguigu.mybatisplus.mapper")
public class MybatisplusApplication {
    public static void main(String[] args) {
        SpringApplication.run(MybatisplusApplication.class, args);
    }
}

测试通用的增删改查方法

假设封装数据的实体类是User(属性id,name,age,email),数据库中的表是user(字段id,name,age,email)

  • 扫描实体类, 抽取实体类的属性
  • 在数据库中找到实体类对应的表以及实体类属性对应的表中字段
  • 调用的BaseMapper接口的方法生成对应的SQL语句注入到MyBatis容器中
方法 功能 对应SQL语句
int insert(User user) 向表中插入一条数据(没有指定id默认基于雪花算法的策略生成一个id) INSERT INTO user (id,name,age,email) VALUES (?,?,?,?)
int deleteById(Long id) 通过id删除记录 DELETE FROM user WHERE id=?
int deleteBatchIds(List< Long> idList) 通过多个id批量删除 DELETE FROM user WHERE id IN ( ? , ? , ? )
int deleteByMap(Map map) 通过map集合中所设置的条件删除记录 DELETE FROM user WHERE name = ? AND age = ?
int updateById(User user) 根据实体类的id修改,不需要修改的字段设置为null UPDATE user SET name=?, age=? WHERE id=?
User selectById(Long id) 根据id查询一条记录 SELECT id,name,age,email FROM user WHERE id= ?
List< User> selectBatchIds(List< Long> idList) 根据多个id查询多个记录 SELECT id,name,age,email FROM user WHERE id IN ( ? , ? )
List< User> selectByMap(Mapmap) 通过map集合中设置的条件查询记录,返回一个list集合 SELECT id,name,age,email FROM user WHERE name = ? AND age = ?
List< User> selectList(null) 根据条件构造器查询数据, null表示没有条件即查询所有数据,返回一个list集合 SELECT id,name,age,email FROM user

测试BaseMapper的增删改方法

@SpringBootTest
public class MybatisPlusTest {
    @Autowired
    private UserMapper userMapper;
    //向表中插入一条数据
    @Test
    public void testInsert(){
        User user = new User(null, "张三", 23, "[email protected]");
        // INSERT INTO user (id,name,age,email) VALUES (?,?,?,?)
        int result = userMapper.insert(user);
        System.out.println("受影响行数:"+result);
        // MyBatis-Plus在插入数据时如果没有指定id默认基于雪花算法的策略生成一个id,如1475754982694199298
        System.out.println("id自动获取:"+user.getId());//获取插入数据的主键id为
    }

    //通过id删除记录
    @Test
    public void testDeleteById(){
        //DELETE FROM user WHERE id=?
        int result = userMapper.deleteById(1475754982694199298L);
        System.out.println("受影响行数:"+result);
    }
    //通过多个id批量删除
    @Test
    public void testDeleteBatchIds(){
        List<Long> idList = Arrays.asList(1L, 2L, 3L);
        //DELETE FROM user WHERE id IN ( ? , ? , ? )
        int result = userMapper.deleteBatchIds(idList);
        System.out.println("受影响行数:"+result);
    }
    
    //通过map集合中所设置的条件删除记录
    @Test
    public void testDeleteByMap(){
        Map<String, Object> map = new HashMap<>();
        map.put("age", 23);
        map.put("name", "张三");
        //DELETE FROM user WHERE name = ? AND age = ?
        int result = userMapper.deleteByMap(map);
        System.out.println("受影响行数:"+result);
    }
    
    //根据实体类的id修改,不需要修改的字段设置为null
    @Test
    public void testUpdateById(){
        User user = new User(4L, "admin", 22, null);
        //UPDATE user SET name=?, age=? WHERE id=?
        int result = userMapper.updateById(user);
        System.out.println("受影响行数:"+result);
    } 
}

测试BaseMapper的查方法

@SpringBootTest
public class MybatisPlusTest {
    @Autowired
    private UserMapper userMapper;

    //根据id查询用户信息
    @Test
    public void testSelectById(){
        //SELECT id,name,age,email FROM user WHERE id= ?
        User user = userMapper.selectById(4L);
        System.out.println(user);
    }

    //根据多个id查询多个用户信息
    @Test
    public void testSelectBatchIds(){
        List<Long> idList = Arrays.asList(4L, 5L);
        //SELECT id,name,age,email FROM user WHERE id IN ( ? , ? )
        List<User> list = userMapper.selectBatchIds(idList);
        list.forEach(System.out::println);
    }

    //通过map集合中设置的条件查询用户信息,返回一个list集合
    @Test
    public void testSelectByMap(){
        Map<String, Object> map = new HashMap<>();
        map.put("age", 22);
        map.put("name", "admin");
        //SELECT id,name,age,email FROM user WHERE name = ? AND age = ?
        List<User> list = userMapper.selectByMap(map);
        list.forEach(System.out::println);
    }

    //查询所有数据,返回一个list集合
    @Test
    public void testSelectList(){
        //SELECT id,name,age,email FROM user
        List<User> list = userMapper.selectList(null);
        list.forEach(System.out::println);
    }
}

自定义SQL

@Repository
public interface UserMapper extends BaseMapper<User> {
    //根据id查询用户信息,返回一个map集合
    Map<String, Object> selectMapById(Long id);
}

指定SQL映射文件的位置,mybatis-plus的mapper-locations属性可以指定配置文件的位置(默认从类路径下的mapper目录下加载)

mybatis-plus:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
  #设置MyBatis-Plus的全局配置
  mapper-locations: SQL映射文件的路径

resources/mapper/UserMapper.xml


DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.atguigu.mybatisplus.mapper.UserMapper">
    
    <select id="selectMapById" resultType="map">
        select id,name,age,email from user where id = #{id}
    select>
mapper>

通用IService中的CRUD

在IService接口中对BaseMapper中的CRUD方法进一步封装, 为了和BaseMapper接口中的方法进行区分,它们方法名采用的前缀不同

  • IService中getXxx查询, listXxx查询集合, removeXxx删除, saveXxx添加, saveOrUpdateBatch(根据有无id判断是添加还是修改操作),updateBatch批量修改
//新增,返回true表示操作成功
boolean save();
//批量新增,集合中的每一个实体类对象就是我们要添加的数据
boolean saveBatch(集合);
//批量新增或者修改方法,判断实体类中的ID是否存在,如果ID不存在执行添加,如果ID存在先执行查询语句,查询结果为空新增否则修改
boolean saveOrUpdateBatch(实体类);

//根据ID删除
boolean removeById();
boolean removeByIds();

//修改
boolean update();
boolean updateById(实体类);

//查询所有
userService.list();
//根据查询条件查询一个实体类对象 ,返回结果不止一条则会抛出异常,如果想默认取第一条结果,可以给这方法传第二个参数为false
userService.getOne(lambdaQueryWrapper);
//分页查询所有
userService.page(pageInfo,lambdaQueryWrapper);
//查询数量
userService.count();
//根据ID查list集合
userService.listByIds();

准备XxxService接口和其实现类

Mybatis-Plus提供的ServiceImpl帮我们实现了IService的所有方法, 我们可以直接使用但是这样不方便后续的功能扩展

// M为XxxMapper接口, 泛型T为要操作的实体对象
public class ServiceImpl<M extends BaseMapper<T>,T> implements IService<T> {
}

准备XxxService接口和XxxServiceImpl接口实现类,若ServiceImpl无法满足业务需求,则在XxxService接口中定义特有的方法

  • 由于自定义的XxxService接口需要继承IService接口, 此时XxxServiceImpl无法直接实现XxxService中从IService继承过来的方法,需要间接继承ServiceImpl实现好的方法
// UserService继承IService模板提供的基础功能
public interface UserService extends IService<User> {
}

@Service
// UserServiceImpl继承了ServiceImpl中的方法,相当于间接的实现了IService或其子类的所有方法
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
}

测试批量操作的方法

方法 功能 SQL语句
count() 测试查询总记录数 SELECT COUNT(*) FROM user
saveBatch(实体类集合) 测试批量插入集合中的所有数据(底层循环调用Mapper的insert方法实现多次插入) INSERT INTO user (id,name,age) VALUES (?,?,?)
@springBootTest
public class MybatisPlusServiceTest{
    @Autowired
    private UserService userService;
    
    // 测试查询总记录数
    @Test
    public void testGetCount(){
        //SELECT COUNT(*) FROM user
        long count = userService.count();
        System.out.println("总记录数:" + count);
    }

    // 测试批量插入
    @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);
        }
        // 因此MP将批量插入放在了通用Service中实现,底层就是在Service中循环调用Mapper的insert方法实现多次插入
        // INSERT INTO user (id,name,age) VALUES (?,?,?)
        userService.saveBatch(users);
    }
}

你可能感兴趣的:(java,mybatis,开发语言)