带有@OneToMany关系的Java Spring Data@Query不返回任何结果

带有@OneToMany关系的Java Spring Data@Query不返回任何结果,java,spring,jpa,assertion,Java,Spring,Jpa,Assertion,我拥有以下实体: @Entity public class Customer extends BaseEntity { private String firstname; private String lastname; @OneToMany(mappedBy = "customer", cascade = CascadeType.ALL) private Set<Address> addresses; ... @Entity publi

我拥有以下实体:

@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;

    ...
@实体
公共类客户扩展BaseEntity{
私有字符串名;
私有字符串lastname;
@OneToMany(mappedBy=“customer”,cascade=CascadeType.ALL)
专用地址集;
...
@实体
公共类地址扩展BaseEntity{
私家弦街;;
私有字符串门号;
私有字符串zipCode;
私人城市;
@许多酮
私人客户;
...
以及以下存储库接口类:

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

}
@存储库
公共接口CustomerRepository扩展了CrudeRepository{
@查询(“从客户c中选择c加入c.a地址,其中(a.city=:cityName)”)
列出findByCity(@Param(“cityName”)字符串城市);
}
现在,我正在尝试运行下面的集成测试,但它失败了,我完全不知道为什么。不幸的是,我是Spring的初学者,我正在尝试学习;-)

@测试
public void testFindCustomerByCity(){
客户=新客户(“最大”、“测试仪”);
地址=新地址(“街道”、“1”、“12345”、“城市”);
HashSet addresses=新的HashSet();
地址。添加(地址);
客户地址(地址);
Customer savedCustomer=customerRepository.save(客户);
Assert.assertTrue(savedCustomer.getId()>0);
List customerList=customerRepository.findByCity(“城市”);
Assert.assertThat(customerList.size(),为(1));
}
错误消息是:

java.lang.AssertionError: 预期:是吗 但是:是吗

为什么结果为空。我的测试设置是否错误?实体关系? 如果您能帮助我,那就好了。

您有
@OneToMany(mappedBy=“customer”,cascade=CascadeType.ALL)
客户
实体的
地址
字段中。这基本上意味着关系由
地址
实体的
客户
字段中的值管理

在测试代码中,您只在客户上设置地址,而不在地址上设置客户。它仍然为空,因此数据库中可能有2条记录,但没有关系。因此,查询不会返回任何内容

在JPA环境中,像使用
setAddresses
一样设置集合是一种非常糟糕的做法(当您在已经存在的实例上这样做时,您将覆盖持久集合).删除
setAddresses
方法,改为在
Customer
上创建
addAddress
方法

@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);
    }

}
@实体
公共类客户扩展BaseEntity{
私有字符串名;
私有字符串lastname;
@OneToMany(mappedBy=“customer”,cascade=CascadeType.ALL)
私有最终集地址=新HashSet();
//没有setter,只有返回不可变集合的getter
公共集getAddresses(){
返回集合.unmodifiableSet(this.addresses);
}
公共无效地址(地址){
地址:setCustomer(本);
本.地址.添加(地址);
}
}
这也会稍微清理一下测试代码

@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));
}
@测试
public void testFindCustomerByCity(){
客户=新客户(“最大”、“测试仪”);
客户地址(新地址(“街道”、“1”、“12345”、“城市”);
Customer savedCustomer=customerRepository.save(客户);
Assert.assertTrue(savedCustomer.getId()>0);
List customerList=customerRepository.findByCity(“城市”);
Assert.assertThat(customerList.size(),为(1));
}

您可以使用这样的查询方法。使用下划线(\ux)获取属性子级

@Repository
public interface CustomerRepository extends JpaRepository<Customer, Long> {
    List<Customer> findByAddresses_City(String city);
}
@存储库
公共接口CustomerRepository扩展了JpaRepository{
列出FindByaAddresss_City(字符串城市);
}

您没有在地址上设置客户,只是在客户中设置了地址。@M好的,我已经添加了
地址。setCustomer(客户)
而且很有效……但我真的不明白……我想,给父实体和子实体就足够了。也许你可以简单解释一下,或者给我一个链接url作为提示……无论如何,谢谢你的快速回答。你有一个地址,地址是
null
客户,按照你指定的地址,关系由address中的customer属性。如果未设置该属性,数据库应如何知道存在关系。同时,执行
setAddresses
也是向客户添加地址的一种非常糟糕的方法。请删除该方法,然后创建一个
addAddress
方法,您可以在其中管理关系。请澄清,当您不使用该方法时在
address
中键入
customer
,保存到数据库中的地址是否没有客户外键?或者查找查询是否有问题?最好知道,对于以后访问此问题的任何人来说。@DuncanKinnear没有客户外键,下划线应该是不必要的。下划线是n必要的,因为城市不是客户财产,而是其子项目(地址)的财产。
@Repository
public interface CustomerRepository extends JpaRepository<Customer, Long> {
    List<Customer> findByAddresses_City(String city);
}