ToB企服应用市场:ToB评测及商务社交产业平台

标题: 我真的不想再用mybatis和其衍生框架了选择自研亦是一种解脱 [打印本页]

作者: 钜形不锈钢水箱    时间: 2023-7-26 11:52
标题: 我真的不想再用mybatis和其衍生框架了选择自研亦是一种解脱
我真的不想再用mybatis和其衍生框架了选择自研亦是一种解脱

文档地址 https://xuejm.gitee.io/easy-query-doc/
GITHUB地址 https://github.com/xuejmnet/easy-query
GITEE地址 https://gitee.com/xuejm/easy-query
为什么要用orm

众所邹知orm的出现让本来以sql实现的复杂繁琐功能大大简化,对于大部分程序员而言一个框架的出现是为了生产力的提升.。dbc定义了交互数据库的规范,任何数据库的操作都是只需要满足jdbc规范即可,而orm就是为了将jdbc的操作进行简化。我个人“有幸”体验过.net和java的两个大orm,只能说差距很大,当然语言上的一些特性也让java在实现orm上有着比较慢的进度,譬如泛型的出现,lambda的出现。
一个好的orm我觉得需要满足以下几点
其实说了这么多总结一下就是一个好的orm应该有ide的提示外加泛型约束帮助开发可以非常顺滑的把代码写下去,并且错误部分可以完全的在编译期间提现出来,运行时错误应该尽可能少的去避免。
为什么放弃mybatis

首先如果你用过其他语言的orm那么再用java的mybatis就像你用惯了java的stream然后去自行处理数据过滤,就像你习惯了kotlin的语法再回到java语法,很难受。这种难受不是自动挡到手动挡的差距,而且自动挡到手推车的差距。

xml配置sql也不知道是哪个“小天才”想出来的,先不说写代码的时候java代码和xml代码跳来跳去,而且xml下>,1[/code]全部使用lambda强类型语法,可以应对多数情况,但是针对join始终没有一个很好地方法。直到我遇到了mpj也就是mybatis-plus-join,但是这个框架也有问题,就是这个逻辑删除在join的子表上不生效,需要手动处理,如果生效那么在where上面,不知道现在怎么样了,当时我也是自行实现了让其出现在join的on后面,但是因为实现是需要实现某个接口的,所以并没有pr代码.
首先定义一个接口
  1. update table set column=column-1 where id=xxx and column>1
复制代码
虽然实现了join但是还是有很多问题出现和bug。
自研orm有哪些特点

easy-query一款无任何依赖的java全新高性能orm支持 单表 多表 子查询 逻辑删除 多租户 差异更新 联级一对一 一对多 多对一 多对多 分库分表(支持跨表查询分页等) 动态表名 数据库列高效加解密支持like crud拦截器 原子更新 vo对象直接返回
文档地址 https://xuejm.gitee.io/easy-query-doc/
GITHUB地址 https://github.com/xuejmnet/easy-query
GITEE地址 https://gitee.com/xuejm/easy-query
单表查询
  1. public interface ISoftDelete {
  2.     Boolean getDeleted();
  3. }
  4. //其中join mapper是我自己的实现,主要还是`WrapperFunction`的那段定义
  5.   @Override
  6.     public Scf4jBaseJoinLinq<T1,TR> on(WrapperFunction<MPJAbstractLambdaWrapper<T1, ?>> onFunction) {
  7.         WrapperFunction<MPJAbstractLambdaWrapper<T1, ?>> join=  on->{
  8.             MPJAbstractLambdaWrapper<T1, ?> apply = onFunction.apply(on);
  9.             if(ISoftDelete.class.isAssignableFrom(joinClass)){
  10.                 SFunction deleted = LambdaHelper.getFunctionField(joinClass, "deleted", Boolean.class);
  11.                 apply.eq(deleted,false);
  12.             }
  13.             return apply;
  14.         };
  15.         joinMapper.setJoinOnFunction(query->{
  16.             query.innerJoin(joinClass,join);
  17.         });
  18.         return joinMapper;
  19.     }
复制代码
  1. //根据条件查询表中的第一条记录
  2. List<Topic> topics = easyQuery
  3.                 .queryable(Topic.class)
  4.                 .limit(1)
  5.                 .toList();
  6. ==> Preparing: SELECT t.`id`,t.`stars`,t.`title`,t.`create_time` FROM t_topic t LIMIT 1
  7. <== Total: 1
  8. //根据条件查询id为3的集合
  9. List<Topic> topics = easyQuery
  10.                 .queryable(Topic.class)
  11.                 .where(o->o.eq(Topic::getId,"3").eq(Topic::geName,"4")
  12.                 .toList();
  13. ==> Preparing: SELECT t.`id`,t.`stars`,t.`title`,t.`create_time` FROM t_topic t WHERE t.`id` = ? AND t.`name` = ?
  14. ==> Parameters: 3(String),4(String)
  15. <== Total: 1
复制代码
多对一

学生和班级
  1. Topic topic = easyQuery
  2.                 .queryable(Topic.class)
  3.                 //join 后面是双参数委托,参数顺序表示join表顺序,可以通过then函数切换
  4.                 .leftJoin(BlogEntity.class, (t, t1) -> t.eq(t1, Topic::getId, BlogEntity::getId))
  5.                 .where(o -> o.eq(Topic::getId, "3"))
  6.                 .firstOrNull();
  7. ==> Preparing: SELECT t.`id`,t.`stars`,t.`title`,t.`create_time` FROM t_topic t LEFT JOIN t_blog t1 ON t.`id` = t1.`id` WHERE t.`id` = ? LIMIT 1
  8. ==> Parameters: 3(String)
  9. <== Total: 1
  10. List<BlogEntity> blogEntities = easyQuery
  11.                 .queryable(Topic.class)
  12.                 //join 后面是双参数委托,参数顺序表示join表顺序,可以通过then函数切换
  13.                 .innerJoin(BlogEntity.class, (t, t1) -> t.eq(t1, Topic::getId, BlogEntity::getId))
  14.                 .where((t, t1) -> t1.isNotNull(BlogEntity::getTitle).then(t).eq(Topic::getId, "3"))
  15.                 //join查询select必须要带对应的返回结果,可以是自定义dto也可以是实体对象,如果不带对象则返回t表主表数据
  16.                 .select(BlogEntity.class, (t, t1) -> t1.columnAll())
  17.                 .toList();
  18. ==> Preparing: SELECT t1.`id`,t1.`create_time`,t1.`update_time`,t1.`create_by`,t1.`update_by`,t1.`deleted`,t1.`title`,t1.`content`,t1.`url`,t1.`star`,t1.`publish_time`,t1.`score`,t1.`status`,t1.`order`,t1.`is_top`,t1.`top` FROM t_topic t INNER JOIN t_blog t1 ON t.`id` = t1.`id` WHERE t1.`title` IS NOT NULL AND t.`id` = ?
  19. ==> Parameters: 3(String)
  20. <== Total: 1
复制代码
一对多

班级和学生
  1. ```java
  2. //SELECT * FROM `t_blog` t1 WHERE t1.`deleted` = ? AND t1.`id` = ?
  3. Queryable<BlogEntity> subQueryable = easyQuery.queryable(BlogEntity.class)
  4.                 .where(o -> o.eq(BlogEntity::getId, "1"));
  5. List<Topic> x = easyQuery
  6.         .queryable(Topic.class).where(o -> o.exists(subQueryable.where(q -> q.eq(o, BlogEntity::getId, Topic::getId)))).toList();
  7. ==> Preparing: SELECT t.`id`,t.`stars`,t.`title`,t.`create_time` FROM `t_topic` t WHERE EXISTS (SELECT 1 FROM `t_blog` t1 WHERE t1.`deleted` = ? AND t1.`id` = ? AND t1.`id` = t.`id`)
  8. ==> Parameters: false(Boolean),1(String)
  9. <== Time Elapsed: 3(ms)
  10. <== Total: 1
  11. //SELECT t1.`id` FROM `t_blog` t1 WHERE t1.`deleted` = ? AND t1.`id` = ?
  12. Queryable<String> idQueryable = easyQuery.queryable(BlogEntity.class)
  13.             .where(o -> o.eq(BlogEntity::getId, "123"))
  14.             .select(String.class, o -> o.column(BlogEntity::getId));//如果子查询in string那么就需要select string,如果integer那么select要integer 两边需要一致
  15. List<Topic> list = easyQuery
  16.         .queryable(Topic.class).where(o -> o.in(Topic::getId, idQueryable)).toList();
  17. ==> Preparing: SELECT t.`id`,t.`stars`,t.`title`,t.`create_time` FROM `t_topic` t WHERE t.`id` IN (SELECT t1.`id` FROM `t_blog` t1 WHERE t1.`deleted` = ? AND t1.`id` = ?)
  18. ==> Parameters: false(Boolean),123(String)
  19. <== Time Elapsed: 2(ms)
  20. <== Total: 0
复制代码
多对多

班级和老师
  1. //@Component //如果是spring
  2. public class MyLogicDelStrategy extends AbstractLogicDeleteStrategy {
  3.     /**
  4.      * 允许datetime类型的属性
  5.      */
  6.     private final Set<Class<?>> allowTypes=new HashSet<>(Arrays.asList(LocalDateTime.class));
  7.     @Override
  8.     protected SQLExpression1<WherePredicate<Object>> getPredicateFilterExpression(LogicDeleteBuilder builder,String propertyName) {
  9.         return o->o.isNull(propertyName);
  10.     }
  11.     @Override
  12.     protected SQLExpression1<ColumnSetter<Object>> getDeletedSQLExpression(LogicDeleteBuilder builder, String propertyName) {
  13. //        LocalDateTime now = LocalDateTime.now();
  14. //        return o->o.set(propertyName,now);
  15.         //上面的是错误用法,将now值获取后那么这个now就是个固定值而不是动态值
  16.         return o->o.set(propertyName,LocalDateTime.now())
  17.                 .set("deletedUser",CurrentUserHelper.getUserId());
  18.     }
  19.     @Override
  20.     public String getStrategy() {
  21.         return "MyLogicDelStrategy";
  22.     }
  23.     @Override
  24.     public Set<Class<?>> allowedPropertyTypes() {
  25.         return allowTypes;
  26.     }
  27. }
  28. //为了测试防止数据被删掉,这边采用不存在的id
  29. logicDelTopic.setId("11xx");
  30. //测试当前人员
  31. CurrentUserHelper.setUserId("easy-query");
  32. long l = easyQuery.deletable(logicDelTopic).executeRows();
  33. ==> Preparing: UPDATE t_logic_del_topic_custom SET `deleted_at` = ?,`deleted_user` = ? WHERE `deleted_at` IS NULL AND `id` = ?
  34. ==> Parameters: 2023-04-01T23:15:13.944(LocalDateTime),easy-query(String),11xx(String)
  35. <== Total: 0
复制代码
动态报名

[code]List blogEntities = easyQuery.queryable(BlogEntity.class)                .asTable(a -> "aa_bb_cc")                .where(o -> o.eq(BlogEntity::getId, "123")).toList();==> Preparing: SELECT t.`id`,t.`create_time`,t.`update_time`,t.`create_by`,t.`update_by`,t.`deleted`,t.`title`,t.`content`,t.`url`,t.`star`,t.`publish_time`,t.`score`,t.`status`,t.`order`,t.`is_top`,t.`top` FROM aa_bb_cc t WHERE t.`deleted` = ? AND t.`id` = ?==> Parameters: false(Boolean),123(String){                    if("t_blog".equals(a)){                        return "aa_bb_cc1";                    }                    return "xxx";                })                .where(o -> o.eq(BlogEntity::getId, "123")).toList();==> Preparing: SELECT t.`id`,t.`create_time`,t.`update_time`,t.`create_by`,t.`update_by`,t.`deleted`,t.`title`,t.`content`,t.`url`,t.`star`,t.`publish_time`,t.`score`,t.`status`,t.`order`,t.`is_top`,t.`top` FROM aa_bb_cc1 t WHERE t.`deleted` = ? AND t.`id` = ?==> Parameters: false(Boolean),123(String) "t_topic_123")                .innerJoin(BlogEntity.class, (t, t1) -> t.eq(t1, Topic::getId, BlogEntity::getId))                .asTable("x_t_blog")                .where((t, t1) -> t1.isNotNull(BlogEntity::getTitle).then(t).eq(Topic::getId, "3"))                .select(BlogEntity.class, (t, t1) -> t1.columnAll()).toList();==> Preparing: SELECT t1.`id`,t1.`create_time`,t1.`update_time`,t1.`create_by`,t1.`update_by`,t1.`deleted`,t1.`title`,t1.`content`,t1.`url`,t1.`star`,t1.`publish_time`,t1.`score`,t1.`status`,t1.`order`,t1.`is_top`,t1.`top` FROM t_topic_123 t INNER JOIN x_t_blog t1 ON t1.`deleted` = ? AND t.`id` = t1.`id` WHERE t1.`title` IS NOT NULL AND t.`id` = ?==> Parameters: false(Boolean),3(String)




欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/) Powered by Discuz! X3.4