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

Adr*_*ian 4 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
public class Address extends BaseEntity {

    private String street;
    private String houseNumber;
    private String zipCode;
    private String city;
    @ManyToOne
    private Customer customer;

    ...
Run Code Online (Sandbox Code Playgroud)

以下存储库接口类:

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

}
Run Code Online (Sandbox Code Playgroud)

现在,我正在尝试运行以下集成测试,但它失败了,我绝对不知道为什么.不幸的是,我是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));
}
Run Code Online (Sandbox Code Playgroud)

错误消息是:

java.lang.AssertionError:预期:是<1>但是:<0>

为什么结果为空.我的测试设置错了吗?实体关系?如果你可以帮助我,那没关系.

win*_*omo 7

您可以使用这样的查询方法.使用下划线(_)来获取属性子项.

@Repository
public interface CustomerRepository extends JpaRepository<Customer, Long> {
    List<Customer> findByAddresses_City(String city);
}
Run Code Online (Sandbox Code Playgroud)

  • 下划线是必要的,因为城市不是客户属性而是其子项(地址)的属性。 (2认同)

M. *_*num 6

您拥有实体中@OneToMany(mappedBy = "customer", cascade = CascadeType.ALL)addresses字段Customer.这基本上意味着关系由实体中customer字段中的值管理Address.

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

像你一样设置集合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);
    }

}
Run Code Online (Sandbox Code Playgroud)

这也可以稍微清理一下您的测试代码.

@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));
}
Run Code Online (Sandbox Code Playgroud)