具有 @OneToMany 关系的 Java Spring Data @Query 不返回结果
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/30643796/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Java Spring Data @Query with @OneToMany relation returns no result
提问by Adrian
I have the following entities:
我有以下实体:
@Entity
public class Customer extends BaseEntity {
private String firstname;
private String lastname;
@OneToMany(mappedBy = "customer", cascade = CascadeType.ALL)
private Set<Address> addresses;
...
@Entity
public class Address extends BaseEntity {
private String street;
private String houseNumber;
private String zipCode;
private String city;
@ManyToOne
private Customer customer;
...
And the following repository interface class:
以及以下存储库接口类:
@Repository
public interface CustomerRepository extends CrudRepository<Customer, Long> {
@Query("select c from Customer c join c.addresses a where (a.city = :cityName)")
List<Customer> findByCity(@Param("cityName")String city);
}
Now, I'm trying to run the following integration test, but it fails and I absolutely don't know why. Unfortunately, I'm a beginner with Spring and I'm trying to learn it ;-)
现在,我正在尝试运行以下集成测试,但它失败了,我完全不知道为什么。不幸的是,我是 Spring 的初学者,我正在努力学习它 ;-)
@Test
public void testFindCustomerByCity() {
Customer customer = new Customer("Max", "Tester");
Address address = new Address("Street", "1", "12345", "City");
HashSet<Address> addresses = new HashSet<Address>();
addresses.add(address);
customer.setAddresses(addresses);
Customer savedCustomer = customerRepository.save(customer);
Assert.assertTrue(savedCustomer.getId() > 0);
List<Customer> customerList = customerRepository.findByCity("City");
Assert.assertThat(customerList.size(), is(1));
}
The error message is:
错误信息是:
java.lang.AssertionError: Expected: is <1> but: was <0>
java.lang.AssertionError:预期:是 <1> 但:是 <0>
Why is the result empty. Is my test setting wrong? The entity relation? It would be fine, if you can help me.
为什么结果是空的。我的测试设置有误吗?实体关系?如果你能帮我就好了。
回答by windupurnomo
You can use query method like this. Use underscore(_) to get property child.
您可以使用这样的查询方法。使用下划线(_) 获取属性 child。
@Repository
public interface CustomerRepository extends JpaRepository<Customer, Long> {
List<Customer> findByAddresses_City(String city);
}
回答by M. Deinum
You have @OneToMany(mappedBy = "customer", cascade = CascadeType.ALL)
on the addresses
field in the Customer
entity. This basically means that the relationship is managed by the value in the customer
field in the Address
entity.
你已经@OneToMany(mappedBy = "customer", cascade = CascadeType.ALL)
在实体addresses
领域Customer
。这基本上意味着关系由实体中customer
字段中的值管理Address
。
In your test code you are only setting the addresses on the customer but not the customer on the address. It is still null, so probably there are 2 records in the database but there is no relation. Hence nothing will be returned from your query.
在您的测试代码中,您只在客户上设置地址,而不是在地址上设置客户。它仍然为空,因此数据库中可能有 2 条记录但没有关系。因此,您的查询不会返回任何内容。
Setting the collection like you do with setAddresses
is a really bad way of doing things in a JPA environment (when you do this on an already existing instance you will overwrite the persistent collection). Remove the setAddresses
method and create an addAddress
method on the Customer
instead.
像setAddresses
在 JPA 环境中那样设置集合是一种非常糟糕的处理方式(当您在已经存在的实例上执行此操作时,您将覆盖持久集合)。删除该setAddresses
方法并addAddress
在其上创建一个方法Customer
。
@Entity
public class Customer extends BaseEntity {
private String firstname;
private String lastname;
@OneToMany(mappedBy = "customer", cascade = CascadeType.ALL)
private final Set<Address> addresses = new HashSet<Address>();
// No setter, only a getter which returns an immutable collection
public Set<Address> getAddresses() {
return Collections.unmodifiableSet(this.addresses);
}
public void addAddress(Address address) {
address.setCustomer(this);
this.addresses.add(address);
}
}
This also cleans up your test code a little.
这也稍微清理了您的测试代码。
@Test
public void testFindCustomerByCity() {
Customer customer = new Customer("Max", "Tester");
customer.addAddress(new Address("Street", "1", "12345", "City"));
Customer savedCustomer = customerRepository.save(customer);
Assert.assertTrue(savedCustomer.getId() > 0);
List<Customer> customerList = customerRepository.findByCity("City");
Assert.assertThat(customerList.size(), is(1));
}