MyBatis or Jpa ? 我都要.

从不缺乏优秀的Orm框架,每个orm框架都有自己独特的魅力.江湖上的两大门派Jpa与Mybatis之争也从来不绝.到底是选择内家功夫见长的Jpa还是外家功夫见长Mybatis,成了技术社区的热门的讨论对象.

Mybatis灵活的SQL,与Jpa的快速开发能否内外兼修,今天介绍一个有趣的增强框架mybatis-nosugar.

Jpa完整的接口过于庞大完全实现没有这个精力.NoSugar仅实现了根据方法名构造sql.方便开发人员快速的应用到项目中去.

JPA式方法名实现查询

说明

和JPA一样根据方法名定义方法,注意参数个数要和条件对应,参数类型和属性类型对应.舍去了部分支持字段.

Jpa方法名规范

支持的操作:
方法前缀操作类型返回类型
find\get\query查询List<T>,T
count总数查询long
exists是否存在查询Optional<Integer>
delete\remove删除int
logicDelete软删除int
示例
public interface StudentMapper extends BaseMapper<Student, String> {

    List<Student> findByNameStartsWithAndAgeBetween(String name, Integer ageStart, Integer ageEnd);

    List<Student> findByNameStartsWithOrAgeBetween(String name, Integer ageStart, Integer ageEnd);

    long countByNameStartsWithAndAgeBetween(String name, Integer ageStart, Integer ageEnd);

    Optional<Integer> existsByNameStartsWithAndAgeBetween(String name, Integer ageStart, Integer ageEnd);

    int deleteByNameStartsWithAndAgeBetween(String name, Integer ageStart, Integer ageEnd);

    int logicDeleteByNameStartsWithAndAgeBetween(String name, Integer ageStart, Integer ageEnd);

}
运行示例
StudentMapper mapper = getMapper(StudentMapper.class);
List<Student> students = mapper.findByNameStartsWithAndAgeBetween("张", 10, 13);
findByNameStartsWithAndAgeBetween : ==>  Preparing: SELECT id AS "id", name AS "name", age AS "age", sex AS "sex", sno AS "sno", phone AS "phone", address AS "address", card_balance AS "cardBalance", status AS "status", version AS "version", created_at AS "createdAt", updated_at AS "updatedAt", disabled_at AS "disabledAt" FROM student WHERE name LIKE ? AND age BETWEEN ? AND ? AND disabled_at IS NULL
findByNameStartsWithAndAgeBetween : ==> Parameters: 张%(String), 10(Integer), 13(Integer)
findByNameStartsWithAndAgeBetween : <==      Total: 1
StudentMapper mapper = getMapper(StudentMapper.class);
List<Student> students = mapper.findByNameStartsWithOrAgeBetween("张", 18, 22);
findByNameStartsWithOrAgeBetween : ==>  Preparing: SELECT id AS "id", name AS "name", age AS "age", sex AS "sex", sno AS "sno", phone AS "phone", address AS "address", card_balance AS "cardBalance", status AS "status", version AS "version", created_at AS "createdAt", updated_at AS "updatedAt", disabled_at AS "disabledAt" FROM student WHERE ( name LIKE ? OR ( age BETWEEN ? AND ? ) ) AND disabled_at IS NULL
findByNameStartsWithOrAgeBetween : ==> Parameters: 张%(String), 18(Integer), 22(Integer)
findByNameStartsWithOrAgeBetween : <==      Total: 2
StudentMapper mapper = getMapper(StudentMapper.class);
long count = mapper.countByNameStartsWithAndAgeBetween("张", 10, 13);
countByNameStartsWithAndAgeBetween : ==>  Preparing: SELECT COUNT(*) FROM student WHERE name LIKE ? AND age BETWEEN ? AND ? AND disabled_at IS NULL
countByNameStartsWithAndAgeBetween : ==> Parameters: 张%(String), 10(Integer), 13(Integer)
countByNameStartsWithAndAgeBetween : <==      Total: 1
StudentMapper mapper = getMapper(StudentMapper.class);
Optional<Integer> exists = mapper.existsByNameStartsWithAndAgeBetween("张", 10, 13);
existsByNameStartsWithAndAgeBetween : ==>  Preparing: SELECT 1 FROM student WHERE name LIKE ? AND age BETWEEN ? AND ? AND disabled_at IS NULL LIMIT 1
existsByNameStartsWithAndAgeBetween : ==> Parameters: 张%(String), 10(Integer), 13(Integer)
existsByNameStartsWithAndAgeBetween : <==      Total: 1
StudentMapper mapper = getMapper(StudentMapper.class);
int delete = mapper.deleteByNameStartsWithAndAgeBetween("张", 10, 13);
deleteByNameStartsWithAndAgeBetween : ==>  Preparing: DELETE FROM student WHERE name LIKE ? AND age BETWEEN ? AND ? AND disabled_at IS NULL
deleteByNameStartsWithAndAgeBetween : ==> Parameters: 张%(String), 10(Integer), 13(Integer)
deleteByNameStartsWithAndAgeBetween : <==    Updates: 1
StudentMapper mapper = getMapper(StudentMapper.class);
int delete = mapper.logicDeleteByNameStartsWithAndAgeBetween("张", 10, 13);
logicDeleteByNameStartsWithAndAgeBetween : ==>  Preparing: UPDATE student SET disabled_at = '2022-01-24 20:40:35' WHERE name LIKE ? AND age BETWEEN ? AND ? AND disabled_at IS NULL
logicDeleteByNameStartsWithAndAgeBetween : ==> Parameters: 张%(String), 10(Integer), 13(Integer)
logicDeleteByNameStartsWithAndAgeBetween : <==    Updates: 1
欺骗一下IDE,让IDEA根据属性名称的自动提示

image.png

让基于Jpa使用方法名的方法用上全新的分页,Count查询

Page<Student> page = mapper.selectPageP3(new PageImpl<>(100, 10), mapper::findByNameStartsWithAndAgeBetween, "张", 10, 13);
long count = mapper.countP3(mapper::findByNameStartsWithAndAgeBetween, "张", 10, 13);
Jpa方法名构建的语句如果写错了,检测能力如何

故意漏写一个参数.

List<Student> findByNameStartsWithAndAgeBetween(String name, Integer ageStart);

启动后检测到参数列表的问题.

com.nosugarice.mybatis.exception.NoSugarException: Method findByNameStartsWithAndAgeBetween expects at least 3 arguments but only found 2.

	at com.nosugarice.mybatis.util.Preconditions.checkArgument(Preconditions.java:51)
	at com.nosugarice.mybatis.util.Preconditions.checkArgument(Preconditions.java:38)
	at com.nosugarice.mybatis.builder.mapper.JpaMapperBuilder.process(JpaMapperBuilder.java:125)
... 
        

故意写错一个属性(name->namea),实体并没有namea这个字段.

List<Student> findByNameaStartsWithAndAgeBetween(String name, Integer ageStart, Integer ageEnd);

启动后检测到属性的问题.

com.nosugarice.mybatis.exception.NoSugarException: No property Namea found for type Student!

	at com.nosugarice.mybatis.util.Preconditions.checkArgument(Preconditions.java:51)
	at com.nosugarice.mybatis.util.Preconditions.checkArgument(Preconditions.java:38)
	at com.nosugarice.mybatis.builder.mapper.JpaMapperBuilder.lambda$process$1(JpaMapperBuilder.java:118)
...

可以看得出来基本通过方法名构建还是可以使用的.

NoSugar不仅于此

  • 无糖配方
  • 开放大量接口给与开发者很大的自由度,让开发者根据自己的程序适配.不必千篇一律
  • 性能非常丝滑,大部分功能超越动态标签,参数越多性能提升越明显
  • 使用简单,不影响原有项目,无需修改原Mybatis类声明,没有重构任何Mybatis基础配置类,只需增加一个属性配置即可开启
  • 无缝增强现有Mybatis项目(+功能),即使现在的项目在使用其他Mybatis框架依旧可增强
  • 部分功能如分页,Count查询,JPA方式的根据方法名查询,可以单独选用
  • 基础的增删改查
  • 条件构造
  • 插入时主键策略
  • 批处理增强模式
  • 全新的通用分页方式,无需插件
  • 全新的通用Count查询方法
  • 软删除
  • 乐观锁
  • 动态表名
  • 更易用的值处理器
  • Jpa式根据方法名查询,删除
Logo

瓜分20万奖金 获得内推名额 丰厚实物奖励 易参与易上手

更多推荐