无法使用 Spring Data JPA 搜索嵌套的对象列表 [英] Cannot search nested list of objects with Spring Data JPA

查看:45
本文介绍了无法使用 Spring Data JPA 搜索嵌套的对象列表的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在使用 Spring Data JPA 查询嵌套的对象列表时遇到问题.

I am having trouble querying a nested list of objects with Spring Data JPA.

这是我的实体:

public class Shipment {
   @Id
   @GeneratedValue(strategy = GenerationType.IDENTITY)
   @Column(updatable = false, nullable = false)
   private Long id;

   @CreationTimestamp
   @Column(updatable = false)
   private Date createdAt;

   @UpdateTimestamp
   private Date updatedAt;

   private String orderId;
   private String deliveryId;

   @OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
   @JoinColumn(name = "shipment")
   private List<Packet> packets;

   // constructors, getters, setters omitted
}

和嵌套列表:

@Entity
public class Packet {

   @Id
   @GeneratedValue(strategy = GenerationType.IDENTITY)
   @Column(updatable = false, nullable = false)
   private Long id;

   @CreationTimestamp
   @Column(updatable = false)
   private Date createdAt;

   @UpdateTimestamp
   private Date updatedAt;

   private String packetId;
   @Enumerated(EnumType.STRING)
   private PacketType packetType;
}

然后我有一个简单的休息端点:

Then I have a simple rest endpoint:

@GetMapping(path = "/shipments", produces = "application/json")
    public List<ShippingIds> getShipments(SearchCriteria searchCriteria) {
    List<Shipment> shipments = shipmentService.getShipmentIds(searchCriteria);
    return buildShipmentIds(shipments);
}

我使用 SearchCriteria 作为 queryParams (/shipments?packetId={packetId}&orderId={orderId}&deliveryId={deliveryId}...

And I am using the SearchCriteria as queryParams (/shipments?packetId={packetId}&orderId={orderId}&deliveryId={deliveryId}...

以及我使用 query by example 的服务:

And my Service where I use query by example:

public List<Shipment> getShipmentIds(SearchCriteria searchCriteria) {
    Shipment shipment = Shipment.builder()
            .orderId(searchCriteria.getOrderId())
            .deliveryId(searchCriteria.getDeliveryId())
            .packetId(searchCriteria.getPacketId())
            .build();

    // My problem is here - How do I do get the associated Shipment object if my search criteria is a packetId? 
    if (searchCriteria.getPacketId()!= null) {
        return shipmentRepository.findByPackets_Packets_packetId(searchCriteria.getPacketId());
    } else {
        Example<Shipment> example = Example.of(shipment);
        return shipmentRepository.findAll(example);
    }
}

还有我的存储库:

@Repository
public interface ShipmentRepository extends JpaRepository<Shipment, Long> {

    List<Shipment> findByPackets_Packets_packetId(String packetId);

}

因为我的对象 Shipment 有一个 Packet 列表,所以我不能简单地将它包含在 Example 中,或者至少我不确定如何.

Since my object Shipment has a list of Packet I cannot simple include it in the Example, or at least I am not sure how.

但是我应该能够根据单个StringpacketId提取相应的Shipment,对吗?

But I should be able to extract the corresponding Shipment based on a single String packetId, right?

我收到一个异常:

原因:org.springframework.data.mapping.PropertyReferenceException:否找到类型 Packet! 的财产包裹!您指的是 'packetId' 吗?遍历路径:Shipment.packets.

Caused by: org.springframework.data.mapping.PropertyReferenceException: No property parcels found for type Packet! Did you mean 'packetId'? Traversed path: Shipment.packets.

我也尝试过自己定义查询:

I also tried to define the Query by myself:

@Query("select s from Shipment s left join s.packets p where s.id = p.shipment")

但后来我得到:

引起:org.hibernate.QueryException:无法解析属性:发货:com.shipment.persistence.model.Packet

Caused by: org.hibernate.QueryException: could not resolve property: shipment of: com.shipment.persistence.model.Packet

虽然装运是我的外键.

任何想法我做错了什么?或者我可以改进什么?

Any ideas what I am doing wrong? Or what I can maybe improve?

推荐答案

你的方向是正确的,但有一些错误.

You are in the right direction, but there are some mistakes.

首先,错误

引起:org.hibernate.QueryException:无法解析属性:发货:com.shipment.persistence.model.Packet

Caused by: org.hibernate.QueryException: could not resolve property: shipment of: com.shipment.persistence.model.Packet

告诉您装运不是您在 Packet 类中定义的字段,因此失败.数据库端有没有关系,如果你想用这个字段查询,必须在类端映射.

is telling you that shipment is not a field you defined on the Packet class, and therefore fails. It does not matter that on database side you have it, if you want to query using this field, it must be mapped on the class side.

话虽如此,为了实现您的初衷,查询所有具有特定id的数据包的货物,没有必要将其添加到您的类中.不需要的原因是你已经在shipping对象端映射了关系,所以没必要再映射到Packet对象上.在其他情况下可能需要它,但在您的情况下不需要.

Having said that, it is not necessary to add it to your class in order to acheive your original intent, which is to query all the shipments that have a packet with a certain id. The reason it is not necessary is that you have already mapped the relation on the shipment object side, so it is not necessary to map it again on the Packet object. It might be required in other scenarios, but not in yours.

在存储库方法之上添加 @Query 注释是正确的.但是,它缺少最重要的部分 - 使用指定的 packetId 获取货物.此外,您提供的连接条件不是必需的,可以省略,因为这是由 Hibernate 在后台处理的,基于@JoinColumn(name = "shipment") 注释的映射.

You were right to add a @Query annotation on top of your repository method. However, it is missing the most important part - getting shipments with the specified packetId. Also, the join condition you supplied is not required and can be omitted, as that is taken care by Hibernate under the hood, based on the mapping annotated with @JoinColumn(name = "shipment").

您的@Query 注释应如下所示:

Your @Query annotation should looks as follows:

@Query("from Shipment s join s.packets p where p.packetId = :packetId")

说明:

  1. 省略了Select s"部分,因为您选择了所有字段,所以它是多余的.
  2. 移除了左连接并替换为连接,因为不需要获取不符合条件的 Shipment 对象.内连接足以告诉 hibernate 在链接对象上准备一个条件.
  3. 添加了条件,该条件将产生具有与给定数据包 ID 匹配的数据包的货件.

这将产生以下 Hibernate 生成的查询:

This will yield the following query generated by Hibernate:

SELECT
    shipment0_.id AS id1_1_0_,
    packets1_.id AS id1_0_1_,
    packets1_.packet_id AS packet_i2_0_1_,
 // and the rest of the fields of both objects
FROM
    shipment shipment0_
INNER JOIN packet packets1_ ON
    shipment0_.id = packets1_.shipment
WHERE
    packets1_.packet_id =?

这篇关于无法使用 Spring Data JPA 搜索嵌套的对象列表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆