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

时间:2015-10-21 22:27:16

标签: java spring jpa spring-data-jpa

我有2个表:USER和ADDRESS。 USER具有第一个,最后一个并计为@Transient以显示用户拥有的地址数。我有一个Spring JPA Data方法,它使用@Query(从user.id中选择用户。*,COUNT(address.id)来获取用户信息和地址COUNT。我已经确认我的查询是好的,但是我无法将COUNT从结果映射到用户类中的count变量。我错过了什么?

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();

1 个答案:

答案 0 :(得分:1)

“@ Transient”注释不应该按照你想要的方式工作。获取用户所有地址的正确方法是使用@OneToMany批注在User实体中映射地址实体,然后进行查询以获取此用户的地址,最后获取Adrdesses的.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注释时,映射的集合是延迟加载的,这意味着你在使用它之前需要从数据库中获取数据。要执行此操作,您可以使用您的查询进行一些修改:

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

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

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

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

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

无论如何,我希望你能用这个答案来表达,祝你好运。