在Mybatis-Plus中提供了ActiveRecord的模式,支持 ActiveRecord 形式调用,实体类只需继承 Model 类即可实现基本 CRUD 操作,简单来说就是一个实体类继承Model类,并通过注解与数据库的表名进行关联,这样就可以通过实体类直接进行表的简单增删改查操作,这样也确实极大的方便了开发人员。

原理理解:

       简单来说Mybatis-plus是基于Mybatis的基础之上进行开发的,其基本操作还是一个Mapper操作中对应一条sql语句,通过参数和返回值来处理sql语句的执行结果。那样我们可以理解Mybatis-Plus的ActiveRecord其实就是Mybatis-Plus给我们提供一些简单的增删改查操作SQl语句的自动生成操作,可以参考上一篇博客mybtais-plus学习--BaseMapper提供的方法及SQL语句生成,在Mybatis提供的BaseMapper中默认提供了一些简单增删改查操作,其通过自动生成sql来初始化Mybatis的一些操作,其最终实现和我们直接基于Mybatis开发是一致的。

抽象类Model

public abstract class Model<T extends Model> implements Serializable {

private static final long serialVersionUID = 1L;

/**
* <p>
* 插入(字段选择插入)
* </p>
*/
@Transactional(rollbackFor = Exception.class)
public boolean insert() {
try (SqlSession session = sqlSession()) {
return SqlHelper.retBool(session.insert(sqlStatement(SqlMethod.INSERT_ONE), this));
}
}

/**
* <p>
* 插入 OR 更新
* </p>
*/
@Transactional(rollbackFor = Exception.class)
public boolean insertOrUpdate() {
if (StringUtils.checkValNull(pkVal())) {
// insert
return insert();
} else {
/*
* 更新成功直接返回,失败执行插入逻辑
*/
return updateById() || insert();
}
}

/**
* <p>
* 根据 ID 删除
* </p>
*
* @param id 主键ID
* @return
*/
@Transactional(rollbackFor = Exception.class)
public boolean deleteById(Serializable id) {
try (SqlSession session = sqlSession()) {
return SqlHelper.delBool(session.delete(sqlStatement(SqlMethod.DELETE_BY_ID), id));
}
}

/**
* <p>
* 根据主键删除
* </p>
*
* @return
*/
@Transactional(rollbackFor = Exception.class)
public boolean deleteById() {
Assert.isFalse(StringUtils.checkValNull(pkVal()), "deleteById primaryKey is null.");
return deleteById(pkVal());
}

/**
* <p>
* 删除记录
* </p>
*
* @param wrapper
* @return
*/
@Transactional(rollbackFor = Exception.class)
public boolean delete(Wrapper wrapper) {
Map<String, Object> map = new HashMap<>(1);
map.put(Constants.WRAPPER, wrapper);
try (SqlSession session = sqlSession()) {
return SqlHelper.delBool(session.delete(sqlStatement(SqlMethod.DELETE), map));
}
}

/**
* <p>
* 更新(字段选择更新)
* </p>
*/
@Transactional(rollbackFor = Exception.class)
public boolean updateById() {
Assert.isFalse(StringUtils.checkValNull(pkVal()), "updateById primaryKey is null.");
// updateById
Map<String, Object> map = new HashMap<>(1);
map.put(Constants.ENTITY, this);
return SqlHelper.retBool(sqlSession().update(sqlStatement(SqlMethod.UPDATE_BY_ID), map));
}

/**
* <p>
* 执行 SQL 更新
* </p>
*
* @param wrapper
* @return
*/
@Transactional(rollbackFor = Exception.class)
public boolean update(Wrapper wrapper) {
Map<String, Object> map = new HashMap<>(2);
map.put(Constants.ENTITY, this);
map.put(Constants.WRAPPER, wrapper);
// update
try (SqlSession session = sqlSession()) {
return SqlHelper.retBool(session.update(sqlStatement(SqlMethod.UPDATE), map));
}
}

/**
* <p>
* 查询所有
* </p>
*
* @return
*/
public List<T> selectAll() {
try (SqlSession session = sqlSession()) {
return session.selectList(sqlStatement(SqlMethod.SELECT_LIST));
}
}

/**
* <p>
* 根据 ID 查询
* </p>
*
* @param id 主键ID
* @return
*/
public T selectById(Serializable id) {
try (SqlSession session = sqlSession()) {
return session.selectOne(sqlStatement(SqlMethod.SELECT_BY_ID), id);
}
}

/**
* <p>
* 根据主键查询
* </p>
*
* @return
*/
public T selectById() {
Assert.isFalse(StringUtils.checkValNull(pkVal()), "selectById primaryKey is null.");
return selectById(pkVal());
}

/**
* <p>
* 查询总记录数
* </p>
*
* @param wrapper
* @return
*/

public List<T> selectList(Wrapper wrapper) {
Map<String, Object> map = new HashMap<>(1);
map.put(Constants.WRAPPER, wrapper);
try (SqlSession session = sqlSession()) {
return session.selectList(sqlStatement(SqlMethod.SELECT_LIST), map);
}
}

/**
* <p>
* 查询一条记录
* </p>
*
* @param wrapper
* @return
*/
public T selectOne(Wrapper wrapper) {
return SqlHelper.getObject(selectList(wrapper));
}

/**
* <p>
* 翻页查询
* </p>
*
* @param page 翻页查询条件
* @param wrapper
* @return
*/
public IPage<T> selectPage(IPage<T> page, Wrapper<T> wrapper) {
Map<String, Object> map = new HashMap<>(2);
map.put(Constants.WRAPPER, SqlHelper.fillWrapper(page, wrapper));
map.put("page", page);
try (SqlSession session = sqlSession()) {
page.setRecords(session.selectList(sqlStatement(SqlMethod.SELECT_PAGE), map));
}
return page;
}

/**
* <p>
* 查询总数
* </p>
*
* @param wrapper
* @return
*/
public int selectCount(Wrapper wrapper) {
Map<String, Object> map = new HashMap<>(1);
map.put(Constants.WRAPPER, wrapper);
try (SqlSession session = sqlSession()) {
return SqlHelper.retCount(session.<Integer>selectOne(sqlStatement(SqlMethod.SELECT_COUNT), map));
}
}

/**
* <p>
* 执行 SQL
* </p>
*/
public SqlRunner sql() {
return new SqlRunner(getClass());
}

/**
* <p>
* 获取Session 默认自动提交
* <p/>
*/
protected SqlSession sqlSession() {
return SqlHelper.sqlSession(getClass());
}

/**
* 获取SqlStatement
*
* @param sqlMethod
* @return
*/
protected String sqlStatement(SqlMethod sqlMethod) {
return sqlStatement(sqlMethod.getMethod());
}

/**
* 获取SqlStatement
*
* @param sqlMethod
* @return
*/
protected String sqlStatement(String sqlMethod) {
return SqlHelper.table(getClass()).getSqlStatement(sqlMethod);
}

/**
* 主键值
*/
protected abstract Serializable pkVal();
}

接下来我们分析一下insert操作到底是做了什么操作

1、调用sqlStatement生成对应的mapper关系

@Transactional(rollbackFor = Exception.class)
public boolean insert() {
try (SqlSession session = sqlSession()) {
return SqlHelper.retBool(session.insert(sqlStatement(SqlMethod.INSERT_ONE), this));
}
}

 2、根据sqlMethod、实体类和要执行的sqlMethod生成对应的insert语句,和BaseMapper的insert方法最终的实现是一致的。

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

 

其实BaseMapper和ActiveRecord这个两个方法是类似的,我们都是要创建一个类来继承抽象类或接口,通过方法名和实体找到对应的Mapper和sql来执行sql语句。