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根据属性名称的自动提示
让基于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式根据方法名查询,删除
|