Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

infinite recursion when querying sql using repository in jpa hibernate

I have two entity, Promotion which contains information about a promotion and Promotion Details which contains list of products in a Promotion. Below is my code.

Promotion Entity:

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

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

}

I want to retrieve one Promotion which is available for a product using JPA.

PromotionRepository:

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

}

But this error occured:

Stacktrace:

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)

I know it seems like Promotion is calling PromotionDetails and PromotionDetails is calling Promotion and so on. But, how do I fix this?

--EDIT--

I would like to add something. I am using Lombok to generate Getter, Setter, and toString

like image 755
Disp Hay Avatar asked Dec 11 '22 19:12

Disp Hay


2 Answers

You can exclude fields from the ToString generation in Lombok. For that, you have to add the @ToString annotation to your class and add the fields, which you want to exclude. In your case, i would exclude the field details in the Promotion class:

@ToString(exclude="details")
public class Promotion {}
like image 82
dunni Avatar answered Jan 12 '23 16:01

dunni


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

You have a recursive call on the toString() of both entities I guess, PromotionDetails is trying to print Promotion while Promotion is trying to print all its PromotionsDetails

A solution would be : Remove either Promotion value from the PromotionDetails toString() method or remove PromotionDetails from the toString() of Promotion.

Becareful with toString() presentation of entities it can cause you trouble.

like image 35
Rafik BELDI Avatar answered Jan 12 '23 16:01

Rafik BELDI