前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >ORM框架DREAM,不一样的开发体验

ORM框架DREAM,不一样的开发体验

原创
作者头像
莫小哀
发布2022-10-30 11:40:40
4240
发布2022-10-30 11:40:40
举报
文章被收录于专栏:DREAM

简介

DREAM(https://github.com/moxa-lzf/dream)是一款基于翻译的以技术为中心,辐射业务持久层框架

特性

跨平台:解析手写sql为抽象树,进而在不同数据库下翻译,并提供接口满足开发者自定义跨平台

函数化:一切sql皆函数,可以用函数代替复杂的sql,根据业务私有化定制函数,极大简化sql写法

缓存机制:一切数据皆可缓存,基于表的缓存,保证读到的数据与数据库一致

插件机制:接口代理,高扩展

监听机制:内置监听器输出sql信息,用于debug开发;提供阻断执行,数据修改功能

简便性:提供了简便的jpa操作,满足简单的sql操作,嵌套高级映射0配置

性能高:从调用开始到拿到结果直线执行,消灭无用的if判断

扩展强:核心功能全部接口工厂实现,可以重写任意接口自主实现功能

开箱即用:多数据源,数据权限,多租户,默认值注入,逻辑删除

优势

精简SQL

查询条件复杂情况

如果当查询条件非常复杂时,这些要查询的字段依旧必须要写,最简单的做法

代码语言:javascript
复制
select * from ...

没有谁建议这样写,而且查询所有字段,效率太低啦,dream提供了极其简单的写法,可改写成

代码语言:javascript
复制
select @all() from ...

引入了@all(),意思是查询所有可以映射成Java属性的字段,而不是数据库所有字段,会随着Java类属性的变化,自动调整查询字段,性能等价于查询具体字段。

查询条件简单情况

简单的查询,如果再继续使用@all()也是不够精简的,因为完全可以将SQL屏蔽,列如采用jpa或者lambda SQL写法,dream也提供了简单的写法,基于注解生成where条件。

为什么基于注解,而不是基于lambda SQL;并非dream不想支持,而是不能支持!

一条简单的SQL在其他orm框架眼里可以说一文不值,即便每次SQL操作重复解析,也没什么大不了影响不到性能,但dream不一样,一条SQL的解析是非常复杂的,而且极度耗时,每一条SQL处理的结果必须保存起来,基于lambda SQL必然的要重复解析SQL

基于注解的生成where条件,虽不易阅读,换来了在前端传入数据给后台时,查询条件间接生成。只需要在Java对象属性字段标记对应注解即可,列如:where条件

代码语言:javascript
复制
where 1=1
<if test="name!=null and name !=''">
and user.name like('%',name,'%')
</if>
<if test="age!=null">
and age in
<foreach item="item" index="index" collection="age"
  open="(" separator="," close=")">
    #{item}
</foreach>
</if>

采用注解形式:

代码语言:javascript
复制
public class UserCondition {
    @Conditional(table = "user",value = ContainsCondition.class)
    private String name;

    @Conditional(value = InCondition.class)
    private List<Integer> age;
}

写法速度上一目了然,注解性能等价于写具体where条件。

分页处理

mybatis分页可以说是所有orm框架里分页最慢的,而且并没有对分页进行优化,列如:统计字段并不需要排序条件,查询字段也是可以精简到select 1。dream框架做到了上述精简。

目前持久层框架普遍的一个问题,每次查询时,都要重新注入分页条件,这一点性能对项目整体而言是微乎其微的,但dream做到了只分页一次,拒绝多次分页,性能等价于直接在SQL写分页条件

极致缓存

任何查询数据都会缓存,而且保证读到的缓存与数据库一致,硬件环境的足够优秀,并不会关注这些,但并不妨碍dream提供这种方案,提高性能

类型转换器

类型转换器在mybatis概念里,就是指定要采用什么样的方式设置占位符值,普遍orm框架为了简单完全是依靠Java属性字段判断的,列如:Java是字符串采用setString方案,但此时如果数据库字段是

int类型,采用setString就不合理啦,dream在选型类型转换器时,是非常严格的,由Java字段返回值类型和数据库字段类型共同决定,列如SQL

代码语言:javascript
复制
select * from user where user_id=@$(userId)

dream会解析到Java对象字段userId的值,保存到表user字段为user_id里,获取到了java字段属性以及数据库字段属性,进而严格选择类型转换器

无感屏蔽映射

使用mybatis需要用resultMap写Java属性与数据库字段的映射

1:编写Java对象接受类

代码语言:javascript
复制
public class User {
    private Integer id;
    private String name;
    private List<Blog> blogList;
}
public class Blog {
    private Integer id;
    private String name;
}

2:编写映射关系

代码语言:javascript
复制
<resultMap id="xxx" type="xxx.xxx.User">
        <result column="id" property="id"></result>
        <result column="name" property="name"></result>
        <collection property="blogList" ofType="xxx.xxx.Blog">
            <result column="id" property="id"></result>
            <result column="name" property="name"></result>
        </collection>
    </resultMap>

所谓无感就是不需要感知就已实现,dream仅仅就需要第一步步骤即可,不需要写任何映射关系,因为dream映射原理前提知道这个字段属于那个表,进而进行高级映射

代码语言:javascript
复制
@View("user")
public class User {
    private Integer id;
    private String name;
    private List<Blog> blogList;
}
@View("blog")
public class Blog {
    private Integer id;
    private String name;
}

无感屏蔽多租户

考虑同一个库,同一个schema情况,将现有项目改写成多租户,实现成本是多少,可能会说成本太大啦,所有SQL基本上都要翻新,而dream却给了你0成本方案,既然无感知,成本自然为0

查询用户表user和文章表blog的前一条数据

代码语言:javascript
复制
SELECT
    * 
FROM
    (
    SELECT
        u.id,
        u.NAME,
        u.age,
        u.email,
        b.id bId,
        b.NAME bName 
    FROM
        USER u
        LEFT JOIN blog b ON b.user_id = u.id 
    ) t_tmp 
    LIMIT 1

若用户表和文章表都存在租户字段,将其改造为多租户,dream可以让你不用修改当前SQL,在启动类添加开启多租户插件即可自动将其改造成多租户

代码语言:javascript
复制
SELECT
    * 
FROM
    (
    SELECT
        u.id,
        u.NAME,
        u.age,
        u.email,
        b.id bId,
        b.NAME bName 
    FROM
        USER u
        LEFT JOIN blog b ON ( b.user_id = u.id ) 
        AND b.tenant_id =? 
    WHERE
    u.tenant_id =?) t_tmp 
    LIMIT 1

dream的识别是高强度的,不会因为SQL复杂,漏加任何租户条件,那性能如何?是等价于直接写租户条件的,无性能损耗

无感屏蔽数据权限

采用mybatis方案进行数据权限隔离,会在where条件注入 ${权限条件},是否可以不写${权限条件},一样完成数据权限注入,这样实现才是真正意义上的权限SQL与业务SQL解耦

同样SQL,需要注入数据权限,假如:查询自己所在部门

代码语言:javascript
复制
SELECT
    * 
FROM
    (
    SELECT
        u.id,
        u.NAME,
        u.age,
        u.email,
        b.id bId,
        b.NAME bName 
    FROM
        USER u
        LEFT JOIN blog b ON b.user_id = u.id 
    ) t_tmp 
    LIMIT 1

开启数据权限插件

代码语言:javascript
复制
SELECT
    * 
FROM
    (
    SELECT
        u.id,
        u.NAME,
        u.age,
        u.email,
        b.id bId,
        b.NAME bName 
    FROM
        USER u
        LEFT JOIN blog b ON b.user_id = u.id 
    WHERE
        u.dept_id = 1 
    ) t_tmp 
    LIMIT 1

u.dept_id=1是开发者自己注入的数据权限,不要担心,dream会解析出别名告诉开发者,完成数据权限注入,此时,SQL非常清爽,性能等价于在SQL直接写注入权限条件

无感屏蔽逻辑删除

有些字段是需要进行逻辑删除的,有些字段不需要,区别在于表是否加了逻辑字段,假如:未来有个需求,这个表不需要逻辑删除,另一张表需要逻辑删除,代码修改必不可少,幸运的是有些框架提供了逻辑删除,自动将delete语句改成update语句,代码量基本上无改动,事实上,表与表之间关联条件以及where条件是否都加了逻辑条件,仍然需要一步一步改。

同样的SQL,假设用户表user和文章表都存在逻辑删除字段,改造为逻辑删除

代码语言:javascript
复制
SELECT
    * 
FROM
    (
    SELECT
        u.id,
        u.NAME,
        u.age,
        u.email,
        b.id bId,
        b.NAME bName 
    FROM
        USER u
        LEFT JOIN blog b ON b.user_id = u.id 
    ) t_tmp 
    LIMIT 1

开启逻辑删除插件

代码语言:javascript
复制
SELECT
    * 
FROM
    (
    SELECT
        u.id,
        u.NAME,
        u.age,
        u.email,
        b.id bId,
        b.NAME bName 
    FROM
        USER u
        LEFT JOIN blog b ON ( b.user_id = u.id ) 
        AND b.del_flag = 0 
    WHERE
        u.del_flag = 0 
    ) t_tmp 
    LIMIT 1

完成了SQL操作的逻辑字段追加,删除数据库里的逻辑字段就不采用逻辑删除,同样,希望某张表采用逻辑删除,加个逻辑字段即可,代码不需要做任何修改,性能等价于直接写逻辑删除条件,性能无损耗

极致的数据库关键字处理

数据库关键字,不是关键字可以不加特殊符号,关键字必须要加,dream提供方案,SQL语句可以不加特殊符号对关键字处理,一样可以正常执行

SQL语句,若user和id为关键字,不做处理会执行报错,正确做法需要对user和id加特殊符号

代码语言:javascript
复制
SELECT
    * 
FROM
    (
    SELECT
        u.id,
        u.NAME,
        u.age,
        u.email,
        b.id bId,
        b.NAME bName 
    FROM
        USER u
        LEFT JOIN blog b ON b.user_id = u.id 
    ) t_tmp 
    LIMIT 1

开启关键字插件

代码语言:javascript
复制
SELECT
    * 
FROM
    (
    SELECT
        u.`id`,
        u.NAME,
        u.age,
        u.email,
        b.`id` bId,
        b.NAME bName 
    FROM
        `USER` u
        LEFT JOIN blog b ON b.user_id = u.`id` 
    ) t_tmp 
    LIMIT 1

自动完成对user和id关键字处理,性能等价于直接写关键字处理

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 简介
  • 特性
  • 优势
    • 精简SQL
      • 查询条件复杂情况
      • 查询条件简单情况
    • 分页处理
      • 极致缓存
        • 类型转换器
          • 无感屏蔽映射
            • 无感屏蔽多租户
              • 无感屏蔽数据权限
                • 无感屏蔽逻辑删除
                  • 极致的数据库关键字处理
                  相关产品与服务
                  数据库
                  云数据库为企业提供了完善的关系型数据库、非关系型数据库、分析型数据库和数据库生态工具。您可以通过产品选择和组合搭建,轻松实现高可靠、高可用性、高性能等数据库需求。云数据库服务也可大幅减少您的运维工作量,更专注于业务发展,让企业一站式享受数据上云及分布式架构的技术红利!
                  领券
                  问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档