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"

这仍然可以执行从用户到颜色的内部连接,但它应该在一个语句中。

如果您想确保避免连接:

  1. 使用 EclipseLink 的 COLUMN JPQL 扩展直接访问外键列。类似于:

    "SELECT new myDto(u.iduser, u.username, COLUMN('FAV_COLOR', u) FROM user u WHERE COLUMN('FAV_COLOR', u) in :listcolors"
    
  2. 使用 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"
    
  3. 除了现有的 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 标记为惰性且不可序列化),因为它无论如何都会有相同的数据。