例如数据库表可能存放有 30 列,本身是列式存储。
实际的查询场景可能每次查询 5 列,且组合可能不一样。
如果用 jpa projections 可能面临需要定义一堆 entiny ,组合数爆炸。
1
bz5314520 2022-06-06 15:35:53 +08:00
楼主是想说,会定义太多的 dto?
|
3
Vaspike 2022-06-06 15:50:53 +08:00
|
4
Tenlearn 2022-06-06 15:51:11 +08:00
这和 jpa 有什么关系,映射到对象不就这样吗
|
5
iosyyy 2022-06-06 15:51:22 +08:00
用 QueryDsl 试试
|
6
sujin190 2022-06-06 15:54:44 +08:00 3
|
7
suman 2022-06-06 16:08:27 +08:00
JPA Specification
|
8
EastLord 2022-06-06 16:29:22 +08:00
querydsl 如何
|
9
bz5314520 2022-06-06 16:37:56 +08:00
@leiuu 我没觉得不优雅,你这样查询估计也是一个接口对应一个前端视图,静态类型检查反而方便调试。这种生成 dto 的体力活,用 IDEA 的插件 JPA BUDDY 生成就行。
|
10
leiuu OP |
11
leiuu OP @EastLord 可行! Dsl 可以搞定。 哈哈,其实想知道「更 jpa 」的写法。目前看 new object 不错。
|
12
sky857412 2022-06-06 17:16:34 +08:00
|
13
hakr 2022-06-06 17:23:32 +08:00
|
14
PopRain 2022-06-06 17:28:56 +08:00
这好像和我之前的问题类似:
https://www.v2ex.com/t/843880#reply10 |
15
nothingistrue 2022-06-06 17:31:11 +08:00 1
你这个返回的列是动态的,这就算到 SQL 那里也不是动态查询,你每次动态选择的列,对 SQL 执行屁影响都没有。WHERE 条件每次都是随机生成的,这才是 ORM 或者 SQL 查询上的动态查询。
请先把你的动态查询给分成两个过程。首先,WHERE 条件动态是一个过程,用 JPA 的 Specification 。然后,返回列的动态是一个过程,这个简单的很,你不论如何都查询出来一个 Entity ( JPA 的要求也必须是一个 Entity 对应一套表),然后在将这个 Entity ,根据接口返回的需要,返回不同的 DTO/VO ,或者仅返回指定字段的 Map (看你的场景,返回哪些列是用得时候才知道的,这样返回 MAP 更合适)。 |
16
Seney 2022-06-06 17:33:40 +08:00
除了上面 dsl/jpql, 还可以用投射,另外定义个 interface 相当于 dto 来接受结果集
|
17
leiuu OP @nothingistrue 对理解有帮助 👍 这里之所以说是动态,因为默认是全部列返回,如果后端是列存数据库性能就会比较差
@Seney 你和楼上头像好像。dto 的方法可以👍,但可能一个 entity 我的场景中可以衍生出 15 个 dto 。他们只有个别字段不一样。 |
19
duyaofei 2022-06-07 07:38:54 +08:00
感觉 jdbctemplate 更适合啊,这场景
|
20
zed1018 2022-06-07 08:56:04 +08:00
我觉得你这个其实更应该是 graphQL ?
|
21
KingOfUSA 2022-06-07 09:34:33 +08:00
@leiuu 用下我的这个库吧 ( https://github.com/ksprider/Surgical ),可以解决一个 entity 对应 n 多种组合的 dto 的场景。
|
22
KevinBlandy 2022-06-07 14:53:27 +08:00 1
Spring Data JPA + QueryDsl 。强烈推荐。投影查询,对象封装,JOIN 检索,UPDATE 部分列。要多舒服有多舒服。
我写过一个 QueryDsl 的案例,你可以看看。 [https://springboot.io/t/topic/4424]( https://springboot.io/t/topic/4424) |
23
leiuu OP @KevinBlandy 手动赞一下 querydsl 很强大 用了 querydsl 是不是一般都不需要 dao 层了 service 层似乎直接就完成工作了
|
24
KevinBlandy 2022-06-07 17:45:06 +08:00
@leiuu 是的。抽象一下,直接在 Controller 就可以通过 Lambda 操作数据库。很方便,不需要写 Service ,Mapper ,xml 以及一堆堆的映射。
|
25
RookieRicardo 2022-06-07 17:50:11 +08:00
|
26
KevinBlandy 2022-06-07 17:55:05 +08:00
@RookieRicardo 看情况呗,我的业务只是为了更新一个字段。我没必要写过 Service ,写个 Dao 。
```java public void handler (){ this.service.apply(query -> { return query.update(user).set(user.enabled, false).where(user.id.eq(1)).exec(); }) } ``` |
27
RookieRicardo 2022-06-07 17:58:11 +08:00
@KevinBlandy 如果没有编程规范的话 怎么样都行
|
28
leiuu OP @RookieRicardo 同意 需要依据团队规范,但这里不知道有没有好的实践方式。
QueryDsl 很灵活,service 涉及多个 entiny 也可以支持 。可能很多需求在 service 层写 dsl 就实现了。所以会纠结是否需要独立抽象 dao 层。 ```java QPerson person = QPerson.person; List<Person> persons = query.from(person) .where(person.firstname.eq(firstname)) .orderBy(person.surname.desc()) .list(person); ... ``` |
29
kongkongye 2022-07-22 19:15:48 +08:00
@nothingistrue 有个问题,如果返回 map 的话是不对 swagger 之类的不太友好,前端单看 swagger 接口说明不知道会返回啥字段,不过好像也没啥好办法
|
30
nothingistrue 2022-07-22 21:19:41 +08:00
严格意义上来说,swagger 的接口定义是要自己写 yaml ,跟你后端定义的对象无关的。能够自动根据 Java 类生成 Swagger 接口定义的,是 Springfox-swagger 插件。而这个插件,是允许你通过注解的方式用自己的定义覆盖默认定于一的,所以及时使用 Map 仍然能够不影响 swagger 这类的接口定义,只是需要多做一些注解 /注释性的工作。
当然,用 Map 不影响,不是鼓励 Map ,首选仍然是特定的类。楼主这里推荐用 Map ,是因为它返回内容当中的字段是不固定的,有可能还是前端要啥后端返回啥,这时候没法定义特定的类了(或者说定义的类就用一次,太浪费),用 Map + 注释 /注解会更省事。 |