Has*_*Bit 2 java hql h2 spring-data spring-boot
情况是:我有一个存储库和两种方法,其中一种看起来像:
//There is no warning about: Activity domain type or valid projection interface expected here...
@Query("select distinct a.creatorId from Activity a")
Optional<List<String>> findAllCreatorIds();
Run Code Online (Sandbox Code Playgroud)
第二种方法如下所示:
//There i have warning about: Activity domain type or valid projection interface expected here
@Query("select distinct a.creatorId from Activity a join a.categories c where c.name in ?1")
Optional<List<String>> findAllCreatorIdsByCategoryNames(Set<String> categoryNames);
Run Code Online (Sandbox Code Playgroud)
看起来可行,并且通过了测试,并且生成的查询如下:
SELECT DISTINCT activity0_.created_by AS col_0_0_
FROM activities activity0_
INNER JOIN category_item categories1_ ON
activity0_.id=categories1_.activity_id
INNER JOIN categories category2_ ON
categories1_.category_id=category2_.id
WHERE category2_.name IN (?)
Run Code Online (Sandbox Code Playgroud)
我进行了更改以使用投影界面。简单的投影界面是:
public interface CreatorIdProjection {
String getCreatorId();
}
Run Code Online (Sandbox Code Playgroud)
查询已更改:
@Query("select a from Activity a join a.categories c where c.name in ?1")
Optional<List<CreatorIdProjection>> findAllCreatorIdsByCategoryNames(Set<String> categoryNames);
Run Code Online (Sandbox Code Playgroud)
也可以。这是生成的查询:
SELECT activity0_.id AS id1_0_,
activity0_.price AS price2_0_,
activity0_.created_by AS created_3_0_,
activity0_.expiration_date AS expirati4_0_,
activity0_.insertts AS insertts5_0_,
activity0_.name AS name6_0_,
activity0_.start_date AS start_da7_0_,
activity0_.updatets AS updatets8_0_
FROM activities activity0_
INNER JOIN category_item categories1_ ON activity0_.id=categories1_.activity_id
INNER JOIN categories category2_ ON categories1_.category_id=category2_.id
WHERE category2_.name IN (?)
Run Code Online (Sandbox Code Playgroud)
我有一些与此案有关的问题:
为什么第一种方法没有警告?
使用投影时,为什么查询在SELECT之后有很多字段?(更准确地说-为什么我们不能使用“从Activity a ...中选择a.creatorId”)
如果结果是我们查询表数据,而不是查询所需的内容,那么发出“ ...域类型或此处需要有效的投影接口”警告的原因是什么?
关于问题#1:
为什么第一种方法没有警告?
这里不涉及Spring Data Projection。您只需执行一个返回标量值列表的查询,然后Optional由 Spring Data 传递该列表(并包装在 中)。因此您不应该收到这样的警告。事实上,我根本无法重现该警告,也无法在源代码中找到它,无论如何,同样的论点也适用于第二种方法。如果它确实产生这样的警告,请提交错误。
对于问题#2a
当我们使用投影时,为什么查询在 SELECT 之后有很多字段?
您可以使用注释准确指定查询@Query,并且它会照此执行。Spring Data 不会解析您的查询并删除不必要的部分,这将是一项巨大的努力却收效甚微,因为您首先提供了查询,您不妨提供一个适合您需求的查询。
对于问题#2b
为什么我们不能使用
select a.creatorId from Activity a...?
你可以(几乎)。您只需指定别名,否则 JPA 会破坏列名称,并且 Spring Data 将不知道它正在查看哪些列。当您不指定别名时,它实际上会告诉您这一点。你应该得到一个例外No aliases found in result tuple! Make sure your query defines aliases!。所以这应该有效:
select a.creatorId as creatorId from Activity a...
Run Code Online (Sandbox Code Playgroud)
另一种方法是在语句中实际调用类的构造函数:
@Query("select new my.super.cool.projection.CreatorId(a.creatorId)")
Run Code Online (Sandbox Code Playgroud)
两种变体都只会查询指定的列。
对于问题#3
...domain type or valid projection interface expected here如果我们的查询查询的是表数据而不是我们需要的数据,那么警告的原因是什么?
我无法重现该警告。我也搜了源码也没找到,所以无法回答这个问题。
| 归档时间: |
|
| 查看次数: |
2564 次 |
| 最近记录: |