一篇文章读懂mybatis-plus原理和CRUD接口

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6

Myabtis-Plus配置

MybatisPlus官网

官方文档上有详细的spring boot配置mybatis-plus的教程此处就不在详细赘述。

mybatis-plus是基于spring完成的只能再spring相关应用上实现。

  1. 引入父工程

在这里插入图片描述
注意mybatis-plus和spring boot的版本匹配不然会出现
在这里插入图片描述

推荐版本

  <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.6.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.1.0</version>
        </dependency>

参考pom依赖

  <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </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>

        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.1.0</version>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.17</version>
        </dependency>


    </dependencies>

配置并连接数据库

  • 创建数据库表

在这里插入图片描述

  • 添加若干数据

在这里插入图片描述

  • application.properties中配置datasource

datasource是连接数据库必须的配置数据库驱动包通过反射来加载这些信息

spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.url=jdbc:mysql://139.9.209.93/task?characterEncoding=utf8&useSSL=false&serverTimezone=UTC&allowPublicKeyRetrieval=true

  • ORM映射

将数据库表映射到java的对象中实现信息交换。

@Data
@TableName("bt_04")
public class BT_04 {

    @TableId(value = "opt_id")
    private Integer id;

    @TableField("drag_start_lat")
    private Double DragStartLat;

    @TableField("drag_start_lon")
    private Double DragStartLon;

    @TableField("drag_end_lat")
    private Double DragEndLat;

    @TableField("drag_end_lon")
    private Double DragEndLon;
}

注意@TableName@TableField相辅相成共同完成ORM映射。后者辅助前者。

名称作用备注
@TableName完成数据库表到对象的映射位于bean的开头参数为数据库表名
@TableField完成字段到属性的映射mp默认下划线命名到驼峰命名转换遵守规则可以省去该注解参数为对象属性
@TableId完成主键的映射参数可以设置自增等条件

car_name[下环线命名]
carName[驼峰命名]
mybatis-plus默认前者转后者。

mp作为myabtis的升级版延续了前身的注解也扩展了许多新的注解

在这里插入图片描述
具体请参考官网 MyBatis-Plus

之前已经通过@TableFieId注解将数据库表实现映射了而关系的桥梁就是sql那么如何应用sql呢
通过mybatis的mapper接口和mapper映射文件关联即可。但是mp有更好的方法就是BaseMapper
一个BaseMapper管理一个映射关系。

myabtis

public interface BTfourMapper {    //extends BaseMapper<BT_04>

    @Select("select * from bt_04")
    List<BT_04> query();
}

mybatis-plus

public interface BTfourMapper extends BaseMapper<BT_04>{ 
    
}

通过BaseMapper的泛型映射后无需编写sql语句更方便。

可以看到BaseMapper中定义了很多接口来满足常规需求

在这里插入图片描述

因此只要集成该接口就可以调用方法由于泛型的绑定实现了表的唯一性。

BaseMapper的CRUD接口

public interface BTfourMapper extends BaseMapper<BT_04>{

}

任意接口继承BaseMapper就可以使用其方法在通过泛型绑定变成相关表的专属mapper例如

//mybatis

public interface UserMapper{
	/**
	*相关CURD操作
	*/
	
	List<User> queryAll();

	...
		
	//每个查询返回结果使用泛型接收所以mapper下的有需要的都要写
}


//mybatis-plus
public interface UserMapper extends BaseMapper<User>{
} 

//在接口处使用泛型后续直接使用

BaseMapper的具体方法及使用参考官网

mapper实例

@SpringBootTest
@RunWith(SpringJUnit4ClassRunner.class)
public class BTtest {

    @Autowired
    BTfourMapper bTfourMapper;

    @Test
    public void method(){
        List<BT_04> bt_04s = bTfourMapper.selectList(null);
        System.out.println(bt_04s);

    }
}

在该单元测试中自动装配的mapper为一个只集成BaseMapper的接口selectList为接口super的方法参数为一个Wraper查询条件包装没有填null。

在这里插入图片描述

BaseMapper中包含了基本的CURD操作其实就是对mapper做了一个包装因为每个mapper无外乎都是CURD操纵具有统一型面向不同的对象又具有多样性包装后的mapper具有通用性。---- 感谢开发团队 😮

下面是BaseMapper的源码

public interface BaseMapper<T> {
    int insert(T entity);

    int deleteById(Serializable id);

    int deleteByMap(@Param("cm") Map<String, Object> columnMap);

    int delete(@Param("ew") Wrapper<T> wrapper);

    int deleteBatchIds(@Param("coll") Collection<? extends Serializable> idList);

    int updateById(@Param("et") T entity);

    int update(@Param("et") T entity, @Param("ew") Wrapper<T> updateWrapper);

    T selectById(Serializable id);

    List<T> selectBatchIds(@Param("coll") Collection<? extends Serializable> idList);

    List<T> selectByMap(@Param("cm") Map<String, Object> columnMap);

    T selectOne(@Param("ew") Wrapper<T> queryWrapper);

    Integer selectCount(@Param("ew") Wrapper<T> queryWrapper);

    List<T> selectList(@Param("ew") Wrapper<T> queryWrapper);

    List<Map<String, Object>> selectMaps(@Param("ew") Wrapper<T> queryWrapper);

    List<Object> selectObjs(@Param("ew") Wrapper<T> queryWrapper);

    IPage<T> selectPage(IPage<T> page, @Param("ew") Wrapper<T> queryWrapper);

    IPage<Map<String, Object>> selectMapsPage(IPage<T> page, @Param("ew") Wrapper<T> queryWrapper);
}

需要注意的是使用BaseMapper一定要加上泛型。

Model的CRUD接口

细心的朋友可能就发现使用mapper时都有相应的xml的文件映射呀或者相应的注解绑定着sql语句呀

是的上面的实例并未出现sql语句是如何实现了的呢对于CURD操作也是具有相似性的例如

// 表a查询

select username,password,status from user

//查询表2

select code,name,status from sys_dict

同理只要将表的字段与对应sql的条件对应上也就具通用性如下所示

package com.baomidou.mybatisplus.core.enums;

public enum SqlMethod {
    INSERT_ONE("insert", "插入一条数据选择字段插入", "<script>\nINSERT INTO %s %s VALUES %s\n</script>"),
    DELETE_BY_ID("deleteById", "根据ID 删除一条数据", "<script>\nDELETE FROM %s WHERE %s=#{%s}\n</script>"),
    DELETE_BY_MAP("deleteByMap", "根据columnMap 条件删除记录", "<script>\nDELETE FROM %s %s\n</script>"),
    DELETE("delete", "根据 entity 条件删除记录", "<script>\nDELETE FROM %s %s\n</script>"),
    DELETE_BATCH_BY_IDS("deleteBatchIds", "根据ID集合批量删除数据", "<script>\nDELETE FROM %s WHERE %s IN (%s)\n</script>"),
    LOGIC_DELETE_BY_ID("deleteById", "根据ID 逻辑删除一条数据", "<script>\nUPDATE %s %s WHERE %s=#{%s} %s\n</script>"),
    LOGIC_DELETE_BY_MAP("deleteByMap", "根据columnMap 条件逻辑删除记录", "<script>\nUPDATE %s %s %s\n</script>"),
    LOGIC_DELETE("delete", "根据 entity 条件逻辑删除记录", "<script>\nUPDATE %s %s %s\n</script>"),
    LOGIC_DELETE_BATCH_BY_IDS("deleteBatchIds", "根据ID集合批量逻辑删除数据", "<script>\nUPDATE %s %s WHERE %s IN (%s) %s\n</script>"),
    UPDATE_BY_ID("updateById", "根据ID 选择修改数据", "<script>\nUPDATE %s %s WHERE %s=#{%s} %s\n</script>"),
    UPDATE("update", "根据 whereEntity 条件更新记录", "<script>\nUPDATE %s %s %s\n</script>"),
    LOGIC_UPDATE_BY_ID("updateById", "根据ID 修改数据", "<script>\nUPDATE %s %s WHERE %s=#{%s} %s\n</script>"),
    LOGIC_UPDATE_ALL_COLUMN_BY_ID("updateAllColumnById", "根据ID 选择修改数据", "<script>\nUPDATE %s %s WHERE %s=#{%s} %s\n</script>"),
    SELECT_BY_ID("selectById", "根据ID 查询一条数据", "SELECT %s FROM %s WHERE %s=#{%s}"),
    SELECT_BY_MAP("selectByMap", "根据columnMap 查询一条数据", "<script>\nSELECT %s FROM %s %s\n</script>"),
    SELECT_BATCH_BY_IDS("selectBatchIds", "根据ID集合批量查询数据", "<script>\nSELECT %s FROM %s WHERE %s IN (%s)\n</script>"),
    SELECT_ONE("selectOne", "查询满足条件一条数据", "<script>\nSELECT %s FROM %s %s\n</script>"),
    SELECT_COUNT("selectCount", "查询满足条件总记录数", "<script>\nSELECT COUNT(%s) FROM %s %s\n</script>"),
    SELECT_LIST("selectList", "查询满足条件所有数据", "<script>\nSELECT %s FROM %s %s\n</script>"),
    SELECT_PAGE("selectPage", "查询满足条件所有数据并翻页", "<script>\nSELECT %s FROM %s %s\n</script>"),
    SELECT_MAPS("selectMaps", "查询满足条件所有数据", "<script>\nSELECT %s FROM %s %s\n</script>"),
    SELECT_MAPS_PAGE("selectMapsPage", "查询满足条件所有数据并翻页", "<script>\nSELECT %s FROM %s %s\n</script>"),
    SELECT_OBJS("selectObjs", "查询满足条件所有数据", "<script>\nSELECT %s FROM %s %s\n</script>"),
    LOGIC_SELECT_BY_ID("selectById", "根据ID 查询一条数据", "SELECT %s FROM %s WHERE %s=#{%s} %s"),
    LOGIC_SELECT_BATCH_BY_IDS("selectBatchIds", "根据ID集合批量查询数据", "<script>\nSELECT %s FROM %s WHERE %s IN (%s) %s\n</script>");

    private final String method;
    private final String desc;
    private final String sql;

    private SqlMethod(String method, String desc, String sql) {
        this.method = method;
        this.desc = desc;
        this.sql = sql;
    }

    public String getMethod() {
        return this.method;
    }

    public String getDesc() {
        return this.desc;
    }

    public String getSql() {
        return this.sql;
    }
}

SqlMethod是mybatis封装sql的类位于com.baomidou.mybatisplus.core.enums包下该类的返回值是一个集合。通过SqlMethod.获取需要的sql语句。

SqlMethod不是泛型没有通用性还需要包装类对其解析封装并具有泛型这个类就是Model

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

package com.baomidou.mybatisplus.extension.activerecord;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.enums.SqlMethod;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Assert;
import com.baomidou.mybatisplus.core.toolkit.GlobalConfigUtils;
import com.baomidou.mybatisplus.core.toolkit.ReflectionKit;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.TableInfoHelper;
import com.baomidou.mybatisplus.extension.toolkit.SqlHelper;
import com.baomidou.mybatisplus.extension.toolkit.SqlRunner;
import java.io.Serializable;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import org.apache.ibatis.session.SqlSession;
import org.mybatis.spring.SqlSessionUtils;

public abstract class Model<T extends Model> implements Serializable {
    private static final long serialVersionUID = 1L;

    public Model() {
    }

    public boolean insert() {
        SqlSession sqlSession = this.sqlSession();

        boolean var2;
        try {
            var2 = SqlHelper.retBool(sqlSession.insert(this.sqlStatement(SqlMethod.INSERT_ONE), this));
        } finally {
            this.closeSqlSession(sqlSession);
        }

        return var2;
    }

    public boolean insertOrUpdate() {
        return !StringUtils.checkValNull(this.pkVal()) && !Objects.isNull(this.selectById(this.pkVal())) ? this.updateById() : this.insert();
    }

    public boolean deleteById(Serializable id) {
        SqlSession sqlSession = this.sqlSession();

        boolean var3;
        try {
            var3 = SqlHelper.delBool(sqlSession.delete(this.sqlStatement(SqlMethod.DELETE_BY_ID), id));
        } finally {
            this.closeSqlSession(sqlSession);
        }

        return var3;
    }

    public boolean deleteById() {
        Assert.isFalse(StringUtils.checkValNull(this.pkVal()), "deleteById primaryKey is null.", new Object[0]);
        return this.deleteById(this.pkVal());
    }

    public boolean delete(Wrapper<T> queryWrapper) {
        Map<String, Object> map = new HashMap(1);
        map.put("ew", queryWrapper);
        SqlSession sqlSession = this.sqlSession();

        boolean var4;
        try {
            var4 = SqlHelper.delBool(sqlSession.delete(this.sqlStatement(SqlMethod.DELETE), map));
        } finally {
            this.closeSqlSession(sqlSession);
        }

        return var4;
    }

    public boolean updateById() {
        Assert.isFalse(StringUtils.checkValNull(this.pkVal()), "updateById primaryKey is null.", new Object[0]);
        Map<String, Object> map = new HashMap(1);
        map.put("et", this);
        SqlSession sqlSession = this.sqlSession();

        boolean var3;
        try {
            var3 = SqlHelper.retBool(sqlSession.update(this.sqlStatement(SqlMethod.UPDATE_BY_ID), map));
        } finally {
            this.closeSqlSession(sqlSession);
        }

        return var3;
    }

    public boolean update(Wrapper<T> updateWrapper) {
        Map<String, Object> map = new HashMap(2);
        map.put("et", this);
        map.put("ew", updateWrapper);
        SqlSession sqlSession = this.sqlSession();

        boolean var4;
        try {
            var4 = SqlHelper.retBool(sqlSession.update(this.sqlStatement(SqlMethod.UPDATE), map));
        } finally {
            this.closeSqlSession(sqlSession);
        }

        return var4;
    }

    public List<T> selectAll() {
        SqlSession sqlSession = this.sqlSession();

        List var2;
        try {
            var2 = sqlSession.selectList(this.sqlStatement(SqlMethod.SELECT_LIST));
        } finally {
            this.closeSqlSession(sqlSession);
        }

        return var2;
    }

    public T selectById(Serializable id) {
        SqlSession sqlSession = this.sqlSession();

        Model var3;
        try {
            var3 = (Model)sqlSession.selectOne(this.sqlStatement(SqlMethod.SELECT_BY_ID), id);
        } finally {
            this.closeSqlSession(sqlSession);
        }

        return var3;
    }

    public T selectById() {
        Assert.isFalse(StringUtils.checkValNull(this.pkVal()), "selectById primaryKey is null.", new Object[0]);
        return this.selectById(this.pkVal());
    }

    public List<T> selectList(Wrapper<T> queryWrapper) {
        Map<String, Object> map = new HashMap(1);
        map.put("ew", queryWrapper);
        SqlSession sqlSession = this.sqlSession();

        List var4;
        try {
            var4 = sqlSession.selectList(this.sqlStatement(SqlMethod.SELECT_LIST), map);
        } finally {
            this.closeSqlSession(sqlSession);
        }

        return var4;
    }

    public T selectOne(Wrapper<T> queryWrapper) {
        return (Model)SqlHelper.getObject(this.selectList(queryWrapper));
    }

    public IPage<T> selectPage(IPage<T> page, Wrapper<T> queryWrapper) {
        Map<String, Object> map = new HashMap(2);
        map.put("ew", queryWrapper);
        map.put("page", page);
        SqlSession sqlSession = this.sqlSession();

        try {
            page.setRecords(sqlSession.selectList(this.sqlStatement(SqlMethod.SELECT_PAGE), map));
        } finally {
            this.closeSqlSession(sqlSession);
        }

        return page;
    }

    public Integer selectCount(Wrapper<T> queryWrapper) {
        Map<String, Object> map = new HashMap(1);
        map.put("ew", queryWrapper);
        SqlSession sqlSession = this.sqlSession();

        Integer var4;
        try {
            var4 = SqlHelper.retCount((Integer)sqlSession.selectOne(this.sqlStatement(SqlMethod.SELECT_COUNT), map));
        } finally {
            this.closeSqlSession(sqlSession);
        }

        return var4;
    }

    public SqlRunner sql() {
        return new SqlRunner(this.getClass());
    }

    protected SqlSession sqlSession() {
        return SqlHelper.sqlSession(this.getClass());
    }

    protected String sqlStatement(SqlMethod sqlMethod) {
        return this.sqlStatement(sqlMethod.getMethod());
    }

    protected String sqlStatement(String sqlMethod) {
        return SqlHelper.table(this.getClass()).getSqlStatement(sqlMethod);
    }

    protected Serializable pkVal() {
        return (Serializable)ReflectionKit.getMethodValue(this, TableInfoHelper.getTableInfo(this.getClass()).getKeyProperty());
    }

    protected void closeSqlSession(SqlSession sqlSession) {
        SqlSessionUtils.closeSqlSession(sqlSession, GlobalConfigUtils.currentSessionFactory(this.getClass()));
    }
}

有了Model后直接使用该类可以进行CRUD但是必须存在对应的mapper继承BaseMapper。基本步骤就是实体类继承Model添加泛型对应Mapper继承BaseMapper然后实体类对象也可以进行CRUD操作。

实例

//实体类继承Model添加泛型
@TableName("user")
public class User extends Model<User> {

    @TableId
    private int id;

    @TableField("username")
    private String username;

    @TableField("password")
    private String password;
}
//对应接口继承BaseMapper
public interface UserMapper extends BaseMapper<User>{
}
//实体类直接调用方法
@SpringBootTest
@RunWith(SpringJUnit4ClassRunner.class)
public class UserMapperTest {

    //@Autowired User user;

    @Test
    public void one(){
        User user = new User();
        List<User> users = user.selectList(null);
        System.out.println(users);
    }
}

Model调用CRUD的接口的限制是需要接收到实体类参数。

IService的CRUD接口

service调用方法基本方法比mapper层调用多了service层

//实体类
@TableName("user_address")
public class UserAddress {

    private int id;

    private int address_id;

    private String detail_address;

    private int user_id;

    private Date create_time;

    private Date update_time;

    private String name;

    private String phone;
}
//mapper层
public interface UserAddressMapper extends BaseMapper<UserAddress> {
}

mapper没有@MapperScan注解的话需要加@Component

service接口继承Iservice并且service接口的实现类要继承ServiceImpl<xxxMapper,pojo>

//service层

//接口
public interface UserAddressService extends IService<UserAddress> {
}

//接口实现类
@Service
public class UserAddressServiceImpl extends ServiceImpl<UserAddressMapper, UserAddress>implements UserAddressService{
}

在这里插入图片描述

具体需要在那层调用要根据实际需求。

//测试
@SpringBootTest
@RunWith(SpringJUnit4ClassRunner.class)
public class UserAddressTest {

    @Autowired
    UserAddressService userAddressService;

    @Test
    public void methodOne(){
        UserAddress one = userAddressService.getById(1);
        System.out.println(one);
    }
}

在这里插入图片描述

总结

1、Model使用映射类pojo继承model直接使用该类可以进行CRUD但是必须存在对应的mapper继承BaseMapper

2、BaseMapper和Iservice
BaseMapper是使用dao层数据进行CRUD只需要进行使用dao层接口继承BaseMapper即可
Iservice是使用service层进行CRUD需要使用service接口继承Iservice并且service接口的实现类要继承ServiceImpl<xxxMapper,pojo>;

BaseMapper和Iservice里面提供的方法都差不多只是Iservice提供了批量操作的实现比如 批量添加、批量修改。

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6