欢迎现代化 Java Orm Easy-Query 加入 Dromara 开源社区
作者介绍
- 名称:xuejm
- dromara 开源组织成员,dromara/easy-query 作者
- java/.net相关开发10年以上经验小菜鸟一枚
- 爱好开源技术乐于专研分享,拥有多个开源项目O(∩_∩)O哈哈~
- 个人空间:https://github.com/xuejmnet 和 https://gitee.com/xuejm
前言
ORM又叫对象关系映射,一款好的ORM不仅仅是支持OM更重要的是把R
合理的利用起来easy-query
就是一款支持对象关系和SQL表达式的现代化ORM.
EasyQuery介绍
EasyQuery是一款Java下面的现代化ORM,拥有强类型、轻量级、高性能特点,致力于解决jdbc查询,支持对象模型关系筛选,隐式查询,纯SQL表达式查询。
框架支持java8及以上版本完全无依赖干净,支持分库分表、字段加密、联级筛选、逻辑删除、多租户、动态表名、无实体CRUD、计算属性、乐观锁、批处理、数据追踪差异更新等一系列功能,并且给予用户极大地扩展和方言自定义功能扩展。
背景
使用现有orm中你是否有以下痛点呢?
1.orm使用都是字符串不易维护,ide无法智能提示
2.orm不支持join或者多表join功能偏弱无法满足group+join 子查询或者from 子查询等情况
3.orm模型联级筛选对象关系过弱,仅支持一对多一对一等的拉取,不支持筛选过滤
4.没有统一的函数来支持映射翻译到所有的数据库
5.orm功能薄弱想支撑业务需要添加各种外部组件来满足业务
6.orm无法和现有pojo体系完美融合兼容
7.不支持分库分表需要额外引入sharding来支持
如果你有以上痛点,那么easy-query
获取能够帮助到你。
使用easy-query可以为开发者带来什么?
1.简单易用高效的api,流式书写带来的便捷性和易维护性,拒绝魔法值
2.强类型只能提示哪怕你是刚入门小白也能在idea的提示下很容易写出想要的代码
3.复杂多表join,子查询,exists面对各种复杂业务场景再也不用担心需要额外引入组件了
4.模型关系查询将ORM的
R
体现的淋漓尽致,不仅仅是简单的查询出结果更能完美的进行对象模型筛选,犹如stream查询数据库一样可以以any
,none
等方法断言和我相关的数据5.结构化DTO任意拉取,可以在用户创建各个模型关系后快速拉去任意结构的对象转成json,不用再烦恼一对一、多对一、一对多、多对多在分页下的获取了
6.完美杜绝n+1带来的性能问题
7.所有功能完全免费永久开源,并且作者自行编写idea插件帮助大家提高效率happy code
实际业务案例
系统的用户架构一般是用户角色(多对多),用户企业多对1,角色菜单多对多
用户筛选
简单筛选
//筛选用户名称包含小明的 List<SysUser> users = easyEntityQuery.queryable(SysUser.class) .where(user->user.name().like("小明")) .toList() //筛选用户名称包含小明的 List<SysUser> users = easyEntityQuery.queryable(SysUser.class) // ifnull(name,'小王') like '小明' .where(user->user.name().nullOrDefault("小王").like("小明")) .toList() //筛选用户名称包含小明并且年龄小于18岁的 List<SysUser> users = easyEntityQuery.queryable(SysUser.class) .where(user->{ //name like ? and age < ? user.name().like("小明"); user.age().lt(18) }) .toList() //返回分页结果 EasyPageResult<SysUser> users = easyEntityQuery.queryable(SysUser.class) .where(user->{ //name like ? and age < ? user.name().like("小明"); user.age().lt(18) }) .orderBy(user->user.createTime().desc())//按用户创建时间倒序 .toPageResult(1,20) //筛选用户名称包含小明或者年龄小于18岁的 List<SysUser> users = easyEntityQuery.queryable(SysUser.class) .where(user->{ user.or(()->{ //name like ? or age < ? user.name().like("小明"); user.age().lt(18) }) }) .toList() //筛选用户名称包含小明或者年龄小于18岁的,只返回用户id和name List<SysUser> users = easyEntityQuery.queryable(SysUser.class) .where(user->{ user.or(()->{ //name like ? or age < ? user.name().like("小明"); user.age().lt(18) }) }) //仅返回id和name .select(user-> user.FETCHER.id().name().fetchProxy()) .toList()
隐式筛选
一对一隐式join
因为用户和企业是多对一的关系所以可以在筛选用户的时候利用对象关系以企业为条件进行筛选从而自动进行join
//筛选用户名称包含小明并且在JAVA企业上班的 List<SysUser> list = easyEntityQuery.queryable(SysUser.class) .where(user -> { user.name().like("小明"); user.company().name().like("JAVA企业"); }).toList(); //from user left join company on ... where user.name like ? and company.name like ?
一对多隐式子查询
当我们在用户对象里面创建好企业关系可以在筛选用户时使用企业作为条件,反之我们在企业模型里面创建好企业和用户的关系我们在筛选企业的时候一样可以使用用户作为条件帮我们快速实现筛选
//筛选企业,筛选条件为企业下的员工存在名字是小明的 List<Company> companies = easyEntityQuery.queryable(Company.class) .where(com -> { com.users().any(u -> { u.name().like("小明"); }); }).toList(); //from company where exists( from user where .... and user.name like ?) //筛选用户条件为用户包含/admin的菜单路径 List<SysUser> userWithMenuContainsAdminPath = easyEntityQuery.queryable(SysUser.class) .where(user -> { //筛选条件为用户下的角色,因为角色不需要过滤所以直接展开判断菜单 //菜单里面存在任意一个路径是'/admin'的即可 user.roles().flatElement().menus().any(menu -> menu.route().like("/admin")); }).toList();
多表显式join
//查询用户join企业表条件是企业的名称包含JAVA企业这几个字 List<Company> companies = easyEntityQuery.queryable(SysUser.class) .leftJoin(Company.class, (user, com) -> user.companyId().eq(com.id())) .where((user, com) -> com.name().like("JAVA企业")) .select((user, com) -> com).toList(); //select company.* from user left join company on user.company_id = company.id where company.name like ?
直接获取用户拥有的菜单
用户和菜单并没有直接关系中间和角色表是多对多中间还有两张表user_role和role_menu表
//查询小明用户拥有的菜单id集合 List<String> menuIds = easyEntityQuery.queryable(SysUser.class) .where(user -> user.name().eq("小明")) .toList(user -> user.roles().flatElement().menus().flatElement().id()); //查询小明用户拥有的菜单集合 List<SysMenu> menus = easyEntityQuery.queryable(SysUser.class) .where(user -> user.name().eq("小明")) .toList(user -> user.roles().flatElement().menus().flatElement());
返回用户结构附带角色
返回结果
{user:{id:xxx,roles:[{...}]}}
//返回小于18岁的用户并且附带角色 List<SysUser> userAndRoles = easyEntityQuery.queryable(SysUser.class) .includes(user -> user.roles()) .where(user -> user.age().lt(18)) .toList(); //返回用户和用户拥有的角色分页返回一对多 EasyPageResult<SysUser> userAndRolePage = easyEntityQuery.queryable(SysUser.class) .includes(user -> user.roles()) .where(user -> user.age().lt(18)) .toPageResult(1, 20);
隐式查询获取匿名结果
有时候我们需要在上文获取中间结果便于java内部计算,大部分orm在这个时候只支持返回map对象,这样会导致在使用时会遍布字符串并且具体类型也会丢失导致使用起来非常不方便
//查询返回用户id,用户名称和用户所在企业名称无需定义中间对象适用临时上下文获取或者group时候的聚合结果 List<Draft3<String, String, String>> userInfo = easyEntityQuery.queryable(SysUser.class) .where(user -> { user.name().like("小明"); user.company().name().like("JAVA企业"); }).select(user -> Select.DRAFT.of( user.id(), user.name(), user.company().name() )).toList(); for (Draft3<String, String, String> userAdnCom : userInfo) { String userId = userAdnCom.getValue1(); String userName = userAdnCom.getValue2(); String companyName = userAdnCom.getValue3(); } List<Draft2<String, Integer>> list2 = easyEntityQuery.queryable(SysUser.class) .where(user -> { user.name().like("小明"); user.company().name().like("JAVA企业"); }) .groupBy(user -> GroupKeys.TABLE1.of(user.name())) .select(group -> Select.DRAFT.of( group.key1(),//user.name group.sum(group.groupTable().age())//sum(user.age) )).toList();
结构化DTO
很多时候我们在访问响应时需要返回自定义的数据结构,而不是整个数据库结构
所以我们这边使用easy-query插件来快速实现构建结构化DTO响应
-
首先我们在idea插件市场安装
EasyQueryAssistant
插件最新版本 -
第二部在需要创建DTO的包右键CreateStructDTO
-
第三步选择需要返回的结构化数据
最终会生成如下dto
/** * this file automatically generated by easy-query struct dto mapping * 当前文件是easy-query自动生成的 结构化dto 映射 * {@link com.easy.query.test.entity.blogtest.SysUser } * * @author easy-query */ @Data public class UserRoleMenuDTO { private String id; private String name; @Navigate(value = RelationTypeEnum.ManyToMany) private List<InternalRoles> roles; /** * {@link com.easy.query.test.entity.blogtest.SysRole } */ @Data public static class InternalRoles { private String id; private String name; @Navigate(value = RelationTypeEnum.ManyToMany) private List<InternalMenus> menus; } /** * {@link com.easy.query.test.entity.blogtest.SysMenu } */ @Data public static class InternalMenus { private String id; private String name; private String route; private String icon; } } //一句话返回需要的结构DTO //通过selectAutoInclude即可映射到我们的DTO 可以返回任意对象关系 List<UserRoleMenuDTO> menus = easyEntityQuery.queryable(SysUser.class) .where(u -> { u.name().like("小明"); u.createTime().rangeClosed(LocalDateTime.now().plusDays(-100),LocalDateTime.now()); }) .selectAutoInclude(UserRoleMenuDTO.class) .toList();
函数翻译
通用函数
方法 | 描述 |
---|---|
nullOrDefault | 如果列为null则返回参数值 |
count | 统计数量返回long |
intCount | 统计数量返回int |
min | 最小值 |
max | 最大值 |
字符串函数
方法 | 描述 |
---|---|
subString | 切割字符串,默认起始0 |
concat | 链接多个列或者值 |
toLower | 转成小写 |
toUpper | 转成大写 |
trim | 去掉前后空格 |
trimStart | 去掉前面空格 |
trimEnd | 去掉后面空格 |
replace | 替换字符串 |
leftPad | 往左补值 |
rightPad | 往右补值 |
join | 字符串多列join组合返回常用语group+逗号组合 |
length | 字符串长度 |
compareTo | 比较字符串大小 |
时间函数
方法 | 描述 |
---|---|
format | 格式化日期支持java格式化 |
plus | 增加时间 |
plusMonths | 增加月份 |
plusYears | 增加年份 |
dayOfYear | 当前天数在一年中代表第几天 |
dayOfWeek | 当前天数在一年中代表第几天 0-6星期日为0 |
year | 返回年份 |
month | 返回月份1-12 |
day | 返回月份中的天数1-31 |
hour | 返回小时0-23 |
minute | 返回分钟0-59 |
second | 返回秒数0-59 |
duration | 返回间隔天/小时/.... a.duration(b,DateTimeDurationEnum.Days) a比b大多少天,如果a小于b则返回负数 两个日期a,b之间相隔多少天 |
now | 当前时间 |
utcNow | 当前UTC时间 |
//函数嵌套处理 List<SysUser> users = easyEntityQuery.queryable(SysUser.class) .where(user -> { user.createTime() .nullOrDefault(LocalDateTime.now()) .plus(1, TimeUnit.DAYS) .format("yyyy-MM-dd HH🇲🇲ss") .eq("2024-01-01 00:00:00"); }).toList(); //SQL:FROM user WHERE DATE_FORMAT(date_add(IFNULL(`create_time`,?), interval (?) microsecond),'%Y-%m-%d %H:%i:%s') = ? //参数:2024-05-20T14:40:08.152(LocalDateTime),86400000000(Long),2024-01-01 00:00:00(String)
如果您对此框架有兴趣那么欢迎您的尝试,也欢迎您的意见建议,框架拥有太多的功能无法在这里意义展示,更多的功能可以访问 github仓库 或gitee仓库 进行查阅
最后
easy-qeury
很高兴加入dromara这个组织希望可以再组织下茁壮成长,为java开源贡献一份自己的微弱力量
最后附上项目地址欢迎大家加入star提交pr issue

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
即时通信软件 ICQ 将于 2024 年 6 月 26 日关停
知名即时通信软件ICQ 宣布将于 2024 年 6 月 26 日关闭——在上线运营近 28 年之后走向终结。 ICQ 官网近日发表声明,称将于 6 月 26 日关闭,它建议用户改用 VK Messenger。 ICQ诞生于 1996 年,是最早的流行即时通讯软件,它最初由以色列公司 Mirabilis 开发,1998 年被 AOL 收购,2010 年被俄罗斯的 Mail.Ru 收购——该公司现改名为 VK。 在其鼎盛期,ICQ 有逾亿用户,但到了 2022 年它的月活用户只剩下了 1100 万。 ICQ 是英语“I seek you”谐音,翻译成中文就是“我找你”。当年,ICQ 提供了多项创新功能,包括多用户聊天、异步离线消息、可恢复文件传输和可搜索目录。 腾讯的 QQ 最初就是模仿 ICQ,原名叫 OICQ(OPEN-ICQ),后因为与 ICQ 的商标争议改名为 QQ。 ICQ 母公司VK 没有透露关闭的原因,多家科技媒体致函目前没有得到相关回复。 但无论如何,ICQ 的关闭表明,该公司宁愿关停该应用,也不愿继续在上面投入运营成本。 目前 VK 运营着一个类似 Facebook 的社...
- 下一篇
OpenAI 将为 iOS 18 提供生成式 AI 功能
5 月 27 日消息,彭博社记者马克・古尔曼(Mark Gurman)在最新一期实时通讯中表示,苹果公司已经与 OpenAI 达成协议,将为今年的 iOS 18 系统提供一系列生成式 AI 功能。 此外,该公司仍在与谷歌进行一系列谈判,试图将 Gemini 作为另一种可选的方案内置在 iOS 系统中。 古尔曼表示,苹果公司预计将在下月举行的 WWDC 2024 上官宣与 OpenAI 达成的伙伴协议。 古尔曼还透露。苹果 iOS 18 将提供以下 AI 功能:照片修饰、语音备忘录转录、帮助撰写电子邮件和信息、根据用户的信息内容人工智能生成表情符号,为现有目录之外的任何场合提供全新的表情符号、改进 Safari 网页搜索、在 Spotlight 中进行更快、更可靠的搜索、用户与 Siri 的交互更自然、专为 Apple Watch 设计的更先进的 Siri 版本,优化主要服务于"移动任务"、智能重现错过的通知和单条信息、网页、新闻文章、文档、笔记等、提供 Xcode 开发人员工具。 另外,iOS 18 中,用户将可以自由放置图标而非局限于当前的「固定对齐」网格,也可以改变所有 App 图...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- CentOS8安装MyCat,轻松搞定数据库的读写分离、垂直分库、水平分库
- CentOS8编译安装MySQL8.0.19
- CentOS6,CentOS7官方镜像安装Oracle11G
- CentOS7,8上快速安装Gitea,搭建Git服务器
- SpringBoot2整合Thymeleaf,官方推荐html解决方案
- MySQL8.0.19开启GTID主从同步CentOS8
- SpringBoot2更换Tomcat为Jetty,小型站点的福音
- Red5直播服务器,属于Java语言的直播服务器
- CentOS6,7,8上安装Nginx,支持https2.0的开启