Spring 带有@Query 的JPA DATA 带回了一个额外的字段

Spring JPA DATA with @Query brings back an extra field

我有 2 个表:USER 和 ADDRESS。 USER 有 first、last 和 count as @Transient 以显示用户拥有的地址数。我有一个 Spring JPA 数据方法,它使用 @Query (select user.*, COUNT(address.id) from ... group by user.id) 来获取用户信息和地址 COUNT。我已经确认我的查询是好的,但我无法将结果中的 COUNT 映射到用户 class 中的计数变量。我错过了什么?

User.java:

@Transient
private int count;
private String first;
private String last;

UserRepository.java

@Query(value = "SELECT "
        + "    user.*, COUNT(address.id) AS COUNT "
        + "FROM "
        + "    user "
        + "        INNER JOIN "
        + "    address ON user.id = address.user_id "
        + "GROUP BY user.ID "
        + "ORDER BY user.last ASC;", nativeQuery = true)
List<User> findUserWithCount();

“@Transient”注释不应该按照您尝试的方式工作。获取用户所有地址的正确方法是使用 @OneToMany 注释映射用户实体中的地址实体,然后查询以获取该用户的地址,最后获取用户实体上的地址的 .size() .

为了更好地解释这一点,我将举一个例子,让我们从映射开始(不包括部分代码):

@Entity
@Table(name = "User")
public class User {
    // All user attributes

    @OneToMany
    public List<Address> addresses;

   // All getters and setters, including addresses get and set.
}

@Entity
@Table(name = "Address")
public class Address {
    // All user attributes getters/setters
}

现在我们已经映射了两个实体,您应该能够通过调用 getAddresses().size() 方法从用户获取地址计数,但是当使用 @OneToMany 注释时,映射的集合是延迟加载的,这意味着您需要在使用 om Java 之前从数据库中获取数据。要执行此提取操作,您可以使用查询进行一些修改:

首先,您不需要使用本机查询,因为您的实体现在已正确映射。其次,您需要用 JPQL 语法重新编写查询,第三,您需要获取地址集合。下面给出的示例可能适用于您的情况:

@Query(value = "SELECT u FROM User u
       LEFT JOIN FETCH u.addresses")
List<User> findUserWithCount();

请注意,并不是说您将无法使用 "last" 字段对数据进行排序,因为它有一个 @Transient 注释,这意味着该字段不会保存在数据库中,这将使其无法在 JPQL 查询中使用。

如果一切都正确完成,您现在应该能够通过调用 getAddresses.size() 方法从用户获取地址计数。

PS:我强烈建议您学习一些 Hibernate 入门教程,使用正确的 Hibernate 规范映射可以很容易地完成您尝试获取用户地址计数的方式。

无论如何,我希望你能通过这个答案,祝你好运。