1
richard1122 2018-08-20 10:18:44 +08:00
|
2
qinxi 2018-08-20 10:19:25 +08:00
试试 JpaSpecificationExecutor 或者 QueryDSL
|
3
lhx2008 2018-08-20 10:31:23 +08:00 via Android
java 写接口语义化不是挺好,如果想不用接口的 orm,可以用 jooq
|
4
u21t20o15 2018-08-20 10:36:39 +08:00
我同事用 Freemark 类似 MyBatis 的方式去做映射,一般需要很复杂的 SQL 才那样写
|
5
linbiaye 2018-08-20 10:46:21 +08:00
老哥,你的这个头像没穿 bra?
|
6
swim2sun 2018-08-20 10:59:38 +08:00
|
7
letitbesqzr 2018-08-20 11:13:02 +08:00
QueryDSL +1 .. 我们引入了 spring data jpa ..但是 所有查询 基础接口 都封装自 QueryDSL,只是某些需要反射来排序 是用的 jpa
|
8
CtrlSpace 2018-08-20 11:29:30 +08:00
写几个接口而已,不算累赘吧。
|
9
abcbuzhiming OP @richard1122 首先谢谢,其次这个实现的还是过于简单。它只能附加字段条件,对注入 limit,group,order 就无能为力,而且无法嵌套,不过你这个提醒了我,我发现我文档看的不仔细,这部分文档上有,但是我看漏了
@qinxi 感谢,我在文档上找到这两个了,QueryDSL 比较理想。但是 JpaSpecificationExecutor。。。怎么会有搞的如此复杂的实现?它有没有什么特长?比如 QueryDSL 做不了它能做的事情?光看功能他做的事情和 QueryDSL 差不多,但是 QueryDSL 比它直观和简单的多了 @letitbesqzr 请教有啥是 QueryDSL 实现不了的?现在选型比较关注框架的弱点方面 |
10
abcbuzhiming OP @CtrlSpace 人的追求是无止境的,你用过 mybatis-plus 就明白了,如果你用过一些动态语言的 ORM 工具比如 ruby 的,你更会明白 java 的这些 ORM 工具局限在哪里
|
11
skypyb 2018-08-20 12:50:36 +08:00
注入 entitymanager 自个写 SQL 啊...
我遇到自带的注解解决不了的一般就自己手动写了。写 HQL 还是原生 SQL 都可以自己定 |
12
rim99 2018-08-20 13:08:19 +08:00 via Android
建议看下文档吧,记得有工厂方法可以传入类对象,定制返回类型的
|
13
passerbytiny 2018-08-20 14:58:58 +08:00 1
首先纠正楼主两点:
一、Hibernate、Jpa 和基于二者的 Spring Data Jpa,都没有“ Dao ”这个概念。 二、既然用了 Spring Data Jpa,那么除非是是否旧的数据库,不应该考虑表、字段等任何数据库方便的概念。 其次,楼主第二段的需求,我没看看明白。 Spring Data Jpa 只是 Hibernate 的一个上层封装,通过约定加自动生成的方式,简化 Jpa/Hibernate 的编码。它本身并不是 ORM,也没有对使用方式做任何强制限制(你可以自由的添加自定义实现)。 |
14
abcbuzhiming OP @passerbytiny
好吧,严谨一点说,spring data jpa 用 repository 来承担了 dao(或者叫 mapper)层的功能 我没看懂“不应该考虑表、字段等任何数据库方便的概念”这句话,你不从数据出发如何建模呢?或者说你觉得正确的思考方式是什么样的呢? 我第二段的需求,是希望能追求灵活性,举个例子,User 对象(表),在场景 1 下需要搜索 userName 字段,到场景 B 需要检索 nickName 字段,按照 spring data jpa 的文档,正统的做法你得在 UserRepository 准备两个 find 方法 findByUserName(String userName) findByNickName(String nickName) 这在我看来是比较麻烦的,因为很多其他 Orm 工具提交这样的做法,以下是伪代码: DYSQL dySQL = new DYSQL() //动态 sql 条件查询类生成 dySQL.eq("列名",列值)..eq("列名",列值).groupy("XXXX").Order("XXX"); select(dySQL); 嗯,其实就是上面提到的 QueryDSL |
15
WispZhan 2018-08-20 15:55:35 +08:00 via Android
@abcbuzhiming 看看 ddd。这些概念是 ddd 的
|
16
passerbytiny 2018-08-20 16:11:11 +08:00 1
@abcbuzhiming Repository 不是 Dao,贫血领域模型用 Dao,常规领域模型用 Repository,它俩永远不会一起使用。
领域驱动设计中的“存储库”的含义是:对象集合以及该集合的读写行为,形象一店的说,就是对象的仓库和仓库管理员。Spring 核心给的 Repository 的定义是:表示“存储库”,若是传统 Java EE 模式(这是好听的说法,说不好停的就是老旧的贫血模型模式),也可以表示 Dao。 下面是 spring core 中 @Repository 的 javadoc 和谷歌翻译 https://docs.spring.io/spring/docs/5.0.8.RELEASE/javadoc-api/org/springframework/stereotype/Repository.html 表示带注释的类是“存储库”,最初由域驱动设计( Evans,2003 )定义为“用于封装模拟对象集合的存储,检索和搜索行为的机制”。 实现传统 Java EE 模式(如“数据访问对象”)的团队也可以将此构造型应用于 DAO 类,但在此之前应注意理解数据访问对象和 DDD 样式存储库之间的区别。这个注释是一个通用的刻板印象,个别团队可能会缩小其语义并在适当时使用。 如此注释的类 DataAccessException 在与 a 一起使用时有资格进行 Spring 翻译 PersistenceExceptionTranslationPostProcessor。带注释的类还阐明了它在整个应用程序体系结构中的作用,以用于工具,方面等。 从 Spring 2.5 开始,这个注释也可以作为一个特化 @Component,允许通过类路径扫描自动检测实现类。 |
17
passerbytiny 2018-08-20 16:17:39 +08:00 1
@abcbuzhiming “不应该考虑表、字段等任何数据库方便的概念”,是领域驱动设计的要求。领域驱动设计中,要求完全按照面向对象的方式去建模,数据库的部分由 Jpa 自动去处理。形象一点的说是:引入了 JPA 的实现( Hibernate 等)后,开发人员只需要设计 Java 类,数据库部分(包括结构和读写 SQL )由 JPA 自动处理。
|
18
passerbytiny 2018-08-20 16:21:48 +08:00 1
@abcbuzhiming 你的这个需求,“场景 1 按照方式一搜索、场景 2 按照方式二搜索”是业务逻辑,不是 Dao/Repository 该干的事。
在传统模式中,Dao 层提供 findByUserName(String userName) findByNickName(String nickName)两个方法,Service 层决定调用哪个方法。 在 DDD 模式中,Repository 提供两个检索方法,领域服务或者应用服务决定调用哪个方法。 |
19
passerbytiny 2018-08-20 16:34:39 +08:00 4
补一下 DDD 的软件架构。
简单分层架构:由下到上依次是:模型层(含 Entity/Aggregation、Value Object、Repository )、Domain Service 层、Application Service 层。Domain Service 层是可选的,并且它仅仅是在调用关系上处于上层,业务关系上它跟模型层是平级的。 依赖倒置架构:由下到上依次是:领域核心层( Entity/Aggregation、Value Object、Domain Service、Repository 接口部分)、Application Service 层、基础设施层( JPA、Hibernate、数据库、Domain Service 技术实现部分……)。此时的分层只表示业务依赖关系,与调用关系无关了。 还有更复杂的架构。所有架构中都没有“ Dao ”,数据库也从来不会参与建模。 |
20
wancaibida 2018-08-20 18:21:05 +08:00
用 grails gorm
|
21
WispZhan 2018-08-20 19:41:05 +08:00 via Android
@passerbytiny 看来老哥也是个 ddd 爱好者
|
22
abcbuzhiming OP @passerbytiny
“在 DDD 模式中,Repository 提供两个检索方法,领域服务或者应用服务决定调用哪个方法。” 我看完了你的描述,但是我这里的需求是:领域服务希望 Repository 的方法能更灵活一点,因为在我的应用场景里 Repository 对应的是持久层关系数据库的访问,对一张表(对象)只提供一个方法就能完成大部分查询,是件很有用的特性。如果 Repository 必须用多个方法才能应对领域服务的需求,这会增加额外的开发成本 |