使用JPA Hibernate中的存储库查询SQL时出现无限递归。

4
我是一个有用的助手,可以翻译文本。
我有两个实体,Promotion 包含有关促销的信息和 Promotion Details 包含在 Promotion 中产品列表。以下是我的代码。 Promotion实体:
@Entity
@Data
public class Promotion {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private long id;

    @OneToMany(mappedBy = "promotion")
    private List<PromotionDetails> details;

    @Column(name = "start_date")
    private Date startDate;

    @Column(name = "end_date")
    private Date endDate;
}

PromotionDetails实体:

@Entity
@IdClass(PromotionDetailsPK.class)
@Data
public class PromotionDetails {

    @Id
    @ManyToOne(optional = false)
    @JoinColumn(name = "promotion_id", referencedColumnName = "promotion_id")
    private Promotion promotion;

    @Id
    @ManyToOne(optional = false)
    @JoinColumn(name="product_id", referencedColumnName="product_id")
    private Product product;

    @Column()
    private double discount;

}

我想使用JPA检索一个可用于产品的PromotionPromotionRepository:
@Repository
public interface PromotionRepository extends JpaRepository<Promotion, Long> {

    @Query("SELECT promotion "
            + "FROM Promotion promotion "
            + "INNER JOIN promotion.details details "
            + "WHERE details.product.id = :productId "
            + "AND CURRENT_DATE BETWEEN promotion.startDate AND promotion.endDate")
    Promotion findOneByProductId(@Param("productId") Long productId);

}

但是出现了这个错误:
堆栈跟踪:
Caused by: java.lang.StackOverflowError: null
    at java.lang.StringBuilder.append(Unknown Source)
    at java.lang.StringBuilder.<init>(Unknown Source)
    at com.example.entity.PromotionDetails.toString(PromotionDetails.java:18)
    at java.lang.String.valueOf(Unknown Source)
    at java.lang.StringBuilder.append(Unknown Source)
    at java.util.AbstractCollection.toString(Unknown Source)
    at org.hibernate.collection.internal.PersistentBag.toString(PersistentBag.java:527)
    at java.lang.String.valueOf(Unknown Source)
    at java.lang.StringBuilder.append(Unknown Source)
    at com.example.entity.Promotion.toString(Promotion.java:18)
    at java.lang.String.valueOf(Unknown Source)
    at java.lang.StringBuilder.append(Unknown Source)
    at com.example.entity.PromotionDetails.toString(PromotionDetails.java:18)
    at java.lang.String.valueOf(Unknown Source)
    at java.lang.StringBuilder.append(Unknown Source)
    at java.util.AbstractCollection.toString(Unknown Source)
    at org.hibernate.collection.internal.PersistentBag.toString(PersistentBag.java:527)
    at java.lang.String.valueOf(Unknown Source)
    at java.lang.StringBuilder.append(Unknown Source)
    at com.example.entity.Promotion.toString(Promotion.java:18)
    ...
    ...
    ...
    ...
    at java.lang.String.valueOf(Unknown Source)
    at java.lang.StringBuilder.append(Unknown Source)
    at jp.co.worksap.stm.entity.sales.PromotionDetails.toString(PromotionDetails.java:18)
    at java.lang.String.valueOf(Unknown Source)
    at java.lang.StringBuilder.append(Unknown Source)
    at java.util.AbstractCollection.toString(Unknown Source)
    at org.hibernate.collection.internal.PersistentBag.toString(PersistentBag.java:527)
    at java.lang.String.valueOf(Unknown Source)
    at java.lang.StringBuilder.append(Unknown Source)
    at jp.co.worksap.stm.entity.sales.Promotion.toString(Promotion.java:18)

我知道这似乎是 Promotion 在调用 PromotionDetails,而 PromotionDetails 又在调用 Promotion,如此往复。但是,我该如何解决这个问题呢? --编辑-- 我想补充一些内容。我正在使用 Lombok 来生成 Getter、Setter 和 toString。

请展示Entity Promotion中的toString方法和PromotionDetails的toString。这就是无限循环开始的地方!位于com.example.entity.Promotion.toString(Promotion.java:18)。 - Si mo
1
嗯,我正在使用Lombok来生成它。 - Disp Hay
那么也许可以排除已链接的实体:@ToString(exclude="id")? - Si mo
2个回答

10
您可以在 Lombok 中排除 ToString 生成的字段。为此,您需要向类中添加 @ToString 注释,并添加要排除的字段。在您的情况下,我会在 Promotion 类中排除字段 details
@ToString(exclude="details")
public class Promotion {}

3
com.example.entity.PromotionDetails.toString(PromotionDetails.java:18)
.
.
.
jp.co.worksap.stm.entity.sales.Promotion.toString(Promotion.java:18)

我猜你在两个实体的toString()中使用了递归调用,PromotionDetails试图打印Promotion,而Promotion则试图打印其所有的PromotionsDetails
解决方案是: 从PromotionDetailstoString()方法中删除Promotion值或从PromotiontoString()中删除PromotionDetails
注意toString()的实体表示方式可能会给您带来麻烦。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接