JPQL 在没有第二个查询的情况下提取关系实体的 pk
JPQL Extract pk of an relation entity without a second query
我有这些实体(只是一个例子,因为我不能分享实名实体):
@Entity
public class User { @Id private BigDecimal id; private String name, private Color favouriteColor }
@Entity
public class Color { @Id private Long colorId; private String colorName;}
在 table 我有这个数据:
USER
ID|NAME|FavColor
1 |John| 1
2 |Sarah| 2
3 |Mike| 1
COLOR
1|Red
2|Blue
现在我想做一个查询来恢复我所有没有 select 颜色实体的用户数据,只有它的 ID。
@Query("new myDto(u.iduser,u.username,u.favcolor) from user u where favcolor in :listcolors")
这让我查询了两个 table,我想要一个唯一的查询,因为我不需要颜色实体,只需要 ID。
--
我正在测试的其他选项正在实现 nativequery,如下所示:
final List<MyDTO> result = new ArrayList<>();
Query q = entityManager.createNativeQuery("SELECT " +
" USER_ID, " +
" USER_NAME, " +
" FAV_COLOR " + +
"FROM USER " +
"WHERE FAV_COLOR IN (?)");
q.setParameter(1, colors.toString().replace("[","").replace("]",""));
Long TRUE = new Long(1L);
final List<Object[]> resultList = q.getResultList();
for (Object[] objects : resultList) {
MyDTOdto = new MyDTO();
dto.userId(((((BigDecimal) objects[0]) != null) ? ((BigDecimal) objects[0]).longValue() : null));
dto.userName(((((String) objects[0]) != null) ? ((String) objects[0]).longValue() : null));
dto.favColor(((((BigDecimal) objects[0]) != null) ? ((BigDecimal) objects[0]).longValue() : null));
result.add(dto);
}
return result;
在这种情况下,我收到错误代码(ORA-1722 - 数字无效)。我不知道我现在可以测试什么。一些想法?谢谢
我猜您对生成的 SQL 和内部联接的使用有问题:当您在 select 子句中调用“u.favcolor”时,您是在告诉 JPA基于 favcolor 关系执行从 User 到 Color 的内部连接。由于 favcolor 是 Color 参考,您将获得完整的颜色行,因为您的本机查询暗示您只需要外键值。如果您只需要 Color 的 fk/ID 值,则查询应为:
"SELECT new myDto(u.iduser, u.username, color.id) FROM user u join u.favcolor color WHERE color.id in :listcolors"
这仍然可以执行从用户到颜色的内部连接,但它应该在一个语句中。
如果您想确保避免连接:
使用 EclipseLink 的 COLUMN JPQL 扩展直接访问外键列。类似于:
"SELECT new myDto(u.iduser, u.username, COLUMN('FAV_COLOR', u) FROM user u WHERE COLUMN('FAV_COLOR', u) in :listcolors"
使用 EclipseLink 本机 query key 功能直接访问 USER table 中的“FAV_COLOR”外键列以进行 JPQL 查询。这需要一个描述符定制程序才能访问,但允许您直接在 JPQL 查询中使用外键值而无需映射它,并且没有 COLUMN 机制将您的 JPQL 查询绑定到特定数据库 table 细节。这将允许以下形式的查询:
"SELECT new myDto(u.iduser, u.username, u.favColorVal FROM user u join u.favcolor color WHERE u.favColorVal in :listcolors"
除了现有的 favColor 参考映射(或根据需要替换它)之外,只需将 FAV_COLOR 映射为基本映射即可:
@Basic
@Column(name="FAV_COLOR", updatable=false, insertable=false)
BigDecimal favColorId
然后您可以使用查询“SELECT new myDto(u.iduser, u.username, u.favColorId FROM user u join u.favColorId color WHERE u.favColorId 在 :listcolors" 中达到相同的效果,但您也可以只 return User 实例(将 favColor 标记为惰性且不可序列化),因为它无论如何都会有相同的数据。
我有这些实体(只是一个例子,因为我不能分享实名实体):
@Entity
public class User { @Id private BigDecimal id; private String name, private Color favouriteColor }
@Entity
public class Color { @Id private Long colorId; private String colorName;}
在 table 我有这个数据:
USER
ID|NAME|FavColor
1 |John| 1
2 |Sarah| 2
3 |Mike| 1
COLOR
1|Red
2|Blue
现在我想做一个查询来恢复我所有没有 select 颜色实体的用户数据,只有它的 ID。
@Query("new myDto(u.iduser,u.username,u.favcolor) from user u where favcolor in :listcolors")
这让我查询了两个 table,我想要一个唯一的查询,因为我不需要颜色实体,只需要 ID。
--
我正在测试的其他选项正在实现 nativequery,如下所示:
final List<MyDTO> result = new ArrayList<>();
Query q = entityManager.createNativeQuery("SELECT " +
" USER_ID, " +
" USER_NAME, " +
" FAV_COLOR " + +
"FROM USER " +
"WHERE FAV_COLOR IN (?)");
q.setParameter(1, colors.toString().replace("[","").replace("]",""));
Long TRUE = new Long(1L);
final List<Object[]> resultList = q.getResultList();
for (Object[] objects : resultList) {
MyDTOdto = new MyDTO();
dto.userId(((((BigDecimal) objects[0]) != null) ? ((BigDecimal) objects[0]).longValue() : null));
dto.userName(((((String) objects[0]) != null) ? ((String) objects[0]).longValue() : null));
dto.favColor(((((BigDecimal) objects[0]) != null) ? ((BigDecimal) objects[0]).longValue() : null));
result.add(dto);
}
return result;
在这种情况下,我收到错误代码(ORA-1722 - 数字无效)。我不知道我现在可以测试什么。一些想法?谢谢
我猜您对生成的 SQL 和内部联接的使用有问题:当您在 select 子句中调用“u.favcolor”时,您是在告诉 JPA基于 favcolor 关系执行从 User 到 Color 的内部连接。由于 favcolor 是 Color 参考,您将获得完整的颜色行,因为您的本机查询暗示您只需要外键值。如果您只需要 Color 的 fk/ID 值,则查询应为:
"SELECT new myDto(u.iduser, u.username, color.id) FROM user u join u.favcolor color WHERE color.id in :listcolors"
这仍然可以执行从用户到颜色的内部连接,但它应该在一个语句中。
如果您想确保避免连接:
使用 EclipseLink 的 COLUMN JPQL 扩展直接访问外键列。类似于:
"SELECT new myDto(u.iduser, u.username, COLUMN('FAV_COLOR', u) FROM user u WHERE COLUMN('FAV_COLOR', u) in :listcolors"
使用 EclipseLink 本机 query key 功能直接访问 USER table 中的“FAV_COLOR”外键列以进行 JPQL 查询。这需要一个描述符定制程序才能访问,但允许您直接在 JPQL 查询中使用外键值而无需映射它,并且没有 COLUMN 机制将您的 JPQL 查询绑定到特定数据库 table 细节。这将允许以下形式的查询:
"SELECT new myDto(u.iduser, u.username, u.favColorVal FROM user u join u.favcolor color WHERE u.favColorVal in :listcolors"
除了现有的 favColor 参考映射(或根据需要替换它)之外,只需将 FAV_COLOR 映射为基本映射即可:
@Basic @Column(name="FAV_COLOR", updatable=false, insertable=false) BigDecimal favColorId
然后您可以使用查询“SELECT new myDto(u.iduser, u.username, u.favColorId FROM user u join u.favColorId color WHERE u.favColorId 在 :listcolors" 中达到相同的效果,但您也可以只 return User 实例(将 favColor 标记为惰性且不可序列化),因为它无论如何都会有相同的数据。