【问题标题】:Custom Query for fetching data from multiple tables in spring Data Jpa用于在 Spring Data Jpa 中从多个表中获取数据的自定义查询
【发布时间】:2024-07-23 19:00:01
【问题描述】:

实体正在关注

产品表

@Entity
public class Product implements Serializable {
/*@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;*/

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Integer id;

    @NotNull(message = "Product name must not be null")
    @NotEmpty
    private String name;


    @ManyToOne
    @JoinColumn(name="category_id")
    private Category category;

    @ManyToMany(mappedBy = "productlist")
    private List<OrderDetail> orderDetail =new ArrayList<OrderDetail>();

//getters setter

订单明细表

@Entity
public class OrderDetail {

     @Id
     @GeneratedValue(strategy = GenerationType.AUTO)
     private Integer id;


     @ManyToOne
     @JoinColumn(name="purchased_By")
     private user PurchasedBy;


    @ManyToMany
     private Set<Product> productlist = new HashSet<Product>();

这些实体生成名为“order_detail_productlist”的表 字段如下 order_detail_id 和 productlist_id

我正在 mysql 编辑器中运行以下查询,并且正在运行

select u.id, r.name from order_detail u inner join order_detail_productlist ur on(u.id=ur.order_detail_id) inner join product r on(ur.productlist_id=r.id) where u.id="?"

但是当我在 Spring 存储库中使用 @Query 注释运行时,这给了我异常。我已尝试根据实体将 Order_detail 的名称更改为 OrderDetail,但在这两种情况下都存在相同的异常。

Caused by: org.hibernate.hql.internal.ast.QuerySyntaxException: Path expected for join! [select r.name from com.example.Domain.OrderDetail u inner join order_detail_productlist ur on(u.id=ur.order_detail_id) inner join Product r on(ur.productlist_id=r.id) where u.id= :id ]

我想要什么。 我正在尝试以这种方式使用。

public final static String product_ordered ="select r.name from OrderDetail u inner join order_detail_productlist ur " +
            "on(u.id=ur.order_detail_id) inner join Product r" +
            " on(ur.productlist_id=r.id)" +
            " where u.id= :id ";

@Query(product_ordered)
public List<Product> findById(@Param("id") int id);

我想从多个表中获取数据,例如订单产品等。

【问题讨论】:

    标签: hibernate spring-data-jpa jpql


    【解决方案1】:

    您的查询不是 hierate 理解的有效 HQL 查询。您可以使用本机 SQL 查询,但提到的用例可以使用 HQL 轻松实现。在此之前,让我们为多对多关联使用正确的注释映射:

    @Entity
    @Table(name = "order_detail")
    public class OrderDetail {
    
         @Id
         @GeneratedValue(strategy = GenerationType.AUTO)
         private Integer id;
    
    
         @ManyToOne
         @JoinColumn(name="purchased_By")
         private user PurchasedBy;
    
    
         @ManyToMany
         @JoinTable(
           name="order_detail_productlist",
           joinColumns=@JoinColumn(name="order_detail_id", referencedColumnName="id"),
           inverseJoinColumns=@JoinColumn(name="productlist_id", referencedColumnName="id"))
          private Set<Product> productlist = new HashSet<Product>();
    

    产品:

    @Entity
    @Table(name ="product")
    public class Product implements Serializable {
    
          @Id
          @GeneratedValue(strategy = GenerationType.AUTO)
          private Integer id;
    
          @NotNull(message = "Product name must not be null")
          @NotEmpty
          @Column(name = "name", nullable = false)
          private String name;
    
    
          @ManyToOne
          @JoinColumn(name="category_id")
          private Category category;
    
          @ManyToMany(mappedBy = "productlist")
          private List<OrderDetail> orderDetail =new ArrayList<OrderDetail>();
    

    并查询:

    public final static String product_ordered ="Select p from Product p Join p.orderDetail od Where od.id = :id";
    
    @Query(product_ordered)
    public List<Product> findById(@Param("id") int id);
    

    Here 是一个适合初学者的 JPA 资源

    【讨论】:

      【解决方案2】:

      您正在做的方式是不可能的,因为您将结果集分配给List&lt;Product&gt;,但查询有一些连接,这意味着查询的结果不是 Product 实体。

      您可以尝试进行原生查询。例如:

      @PersistenceContext
      private EntityManager entityManager;
      
      public List<Object[]> customQuery(int id) {
          Query nativeQuery = entityManager.createNativeQuery(product_ordered).setParameter("id",id);
          return nativeQuery.getResultList();
      }
      

      【讨论】: