MybatisPlus官网
官方文档上有详细的spring boot配置mybatis-plus的教程,此处就不在详细赘述。
mybatis-plus是基于spring完成的只能再spring相关应用上实现。
注意mybatis-plus和spring boot的版本匹配不然会出现
推荐版本
org.springframework.boot spring-boot-starter-parent 2.1.6.RELEASE
com.baomidou mybatis-plus-boot-starter 3.1.0
参考pom依赖
org.springframework.boot spring-boot-starter-web org.projectlombok lombok true org.springframework.boot spring-boot-starter-test test com.baomidou mybatis-plus-boot-starter 3.1.0 mysql mysql-connector-java 8.0.17
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
将数据库表映射到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@Select("select * from bt_04")List query();
}
mybatis-plus
public interface BTfourMapper extends BaseMapper{ }
通过BaseMapper的泛型映射后无需编写sql语句更方便。
可以看到BaseMapper中定义了很多接口来满足常规需求
因此只要集成该接口就可以调用方法,由于泛型的绑定实现了表的唯一性。
public interface BTfourMapper extends BaseMapper{}
任意接口继承BaseMapper
就可以使用其方法,在通过泛型绑定变成相关表的专属mapper,例如
//mybatispublic interface UserMapper{/***相关CURD操作*/List queryAll();...//每个查询返回结果使用泛型接收,所以mapper下的有需要的都要写
}//mybatis-plus
public interface UserMapper extends BaseMapper{
} //在接口处使用泛型,后续直接使用
BaseMapper的具体方法及使用参考官网
mapper实例:
@SpringBootTest
@RunWith(SpringJUnit4ClassRunner.class)
public class BTtest {@AutowiredBTfourMapper bTfourMapper;@Testpublic void method(){List 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 {int insert(T entity);int deleteById(Serializable id);int deleteByMap(@Param("cm") Map columnMap);int delete(@Param("ew") Wrapper wrapper);int deleteBatchIds(@Param("coll") Collection extends Serializable> idList);int updateById(@Param("et") T entity);int update(@Param("et") T entity, @Param("ew") Wrapper updateWrapper);T selectById(Serializable id);List selectBatchIds(@Param("coll") Collection extends Serializable> idList);List selectByMap(@Param("cm") Map columnMap);T selectOne(@Param("ew") Wrapper queryWrapper);Integer selectCount(@Param("ew") Wrapper queryWrapper);List selectList(@Param("ew") Wrapper queryWrapper);List
需要注意的是使用BaseMapper一定要加上泛型。
细心的朋友可能就发现使用mapper时都有相应的xml的文件映射呀,或者相应的注解绑定着sql语句呀?
是的,上面的实例并未出现sql语句,是如何实现了的呢?对于CURD操作也是具有相似性的,例如
// 表a查询select username,password,status from user//查询表2select code,name,status from sys_dict
同理只要将表的字段与对应sql的条件对应上也就具通用性,如下所示:
package com.baomidou.mybatisplus.core.enums;public enum SqlMethod {INSERT_ONE("insert", "插入一条数据(选择字段插入)", ""),DELETE_BY_ID("deleteById", "根据ID 删除一条数据", ""),DELETE_BY_MAP("deleteByMap", "根据columnMap 条件删除记录", ""),DELETE("delete", "根据 entity 条件删除记录", ""),DELETE_BATCH_BY_IDS("deleteBatchIds", "根据ID集合,批量删除数据", ""),LOGIC_DELETE_BY_ID("deleteById", "根据ID 逻辑删除一条数据", ""),LOGIC_DELETE_BY_MAP("deleteByMap", "根据columnMap 条件逻辑删除记录", ""),LOGIC_DELETE("delete", "根据 entity 条件逻辑删除记录", ""),LOGIC_DELETE_BATCH_BY_IDS("deleteBatchIds", "根据ID集合,批量逻辑删除数据", ""),UPDATE_BY_ID("updateById", "根据ID 选择修改数据", ""),UPDATE("update", "根据 whereEntity 条件,更新记录", ""),LOGIC_UPDATE_BY_ID("updateById", "根据ID 修改数据", ""),LOGIC_UPDATE_ALL_COLUMN_BY_ID("updateAllColumnById", "根据ID 选择修改数据", ""),SELECT_BY_ID("selectById", "根据ID 查询一条数据", "SELECT %s FROM %s WHERE %s=#{%s}"),SELECT_BY_MAP("selectByMap", "根据columnMap 查询一条数据", ""),SELECT_BATCH_BY_IDS("selectBatchIds", "根据ID集合,批量查询数据", ""),SELECT_ONE("selectOne", "查询满足条件一条数据", ""),SELECT_COUNT("selectCount", "查询满足条件总记录数", ""),SELECT_LIST("selectList", "查询满足条件所有数据", ""),SELECT_PAGE("selectPage", "查询满足条件所有数据(并翻页)", ""),SELECT_MAPS("selectMaps", "查询满足条件所有数据", ""),SELECT_MAPS_PAGE("selectMapsPage", "查询满足条件所有数据(并翻页)", ""),SELECT_OBJS("selectObjs", "查询满足条件所有数据", ""),LOGIC_SELECT_BY_ID("selectById", "根据ID 查询一条数据", "SELECT %s FROM %s WHERE %s=#{%s} %s"),LOGIC_SELECT_BATCH_BY_IDS("selectBatchIds", "根据ID集合,批量查询数据", "");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 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 queryWrapper) {Map 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 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 updateWrapper) {Map 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 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 selectList(Wrapper queryWrapper) {Map 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 queryWrapper) {return (Model)SqlHelper.getObject(this.selectList(queryWrapper));}public IPage selectPage(IPage page, Wrapper queryWrapper) {Map 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 queryWrapper) {Map 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 {@TableIdprivate int id;@TableField("username")private String username;@TableField("password")private String password;
}
//对应接口继承BaseMapper
public interface UserMapper extends BaseMapper{
}
//实体类直接调用方法
@SpringBootTest
@RunWith(SpringJUnit4ClassRunner.class)
public class UserMapperTest {//@Autowired User user;@Testpublic void one(){User user = new User();List users = user.selectList(null);System.out.println(users);}
}
Model调用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 {
}
mapper没有@MapperScan注解的话需要加@Component
service接口继承Iservice,并且service接口的实现类要继承ServiceImpl
//service层//接口
public interface UserAddressService extends IService {
}//接口实现类
@Service
public class UserAddressServiceImpl extends ServiceImplimplements UserAddressService{
}
具体需要在那层调用要根据实际需求。
//测试
@SpringBootTest
@RunWith(SpringJUnit4ClassRunner.class)
public class UserAddressTest {@AutowiredUserAddressService userAddressService;@Testpublic 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
BaseMapper和Iservice里面提供的方法都差不多,只是Iservice提供了批量操作的实现,比如: 批量添加、批量修改。