۱۳۹۷ بهمن ۱۸, پنجشنبه

Lombok، Hibernate و خطای 'StackOverflowError: null'!

یکی از کتابخانه های محبوبم در جاوا Project Lombok، کمک بزرگی برای تمیز و خوانا بودن کد، برای اینکه متوجه منظورم بشید فقط یه نگاه به نمونه کد اش برای @Data (اینجا) بندازید و اونوقت شما هم به من حق میدید!
 ولی استفاده از @Data روی یک entity و استفاده از این شی داخل یک entity دیگه (مثلا یک Set از کامنتهای یک پست بلاگ)، شما رو با خطای java.lang.StackOverflowError: null مواجه میکنه! @Data یک میانبری برای این انوتیشن های Lombok:
  • @Getter
  • @Setter
  • @ToString
  • @RequiredArgsConstructor
  • @EqualsAndHashCode
 و همه چی بخاطر @EqualsAndHashCode! من یک راه حل برای این مشکل در آخرین کامنت این سوال StackOverflow پیدا کردم: https://stackoverflow.com/questions/34972895 که میگه باید بعد از @Data از این انوتیشن استفاده کنیم و فیلد های رابطه ای رو از متدهای Equals و Hash حذف کنیم:

@EqualsAndHashCode(exclude="entries")
من تو پروژه Feader ام از این کتابخانه استفاده کردم و میتونید به عنوان یه نمونه روش بررسی هاتون رو انجام بدید. Feed.java و FeedEntry.java کلاسهایی هستند که مورد استفاده قرار گرفتند، FeedEntry داخل Feed استفاده شده (مثل کامنتهای یک پست):

package com.glinboy.feader.model;

import java.util.Set;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.Lob;
import javax.persistence.ManyToMany;
import javax.persistence.OneToMany;

import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;

import lombok.Data;
import lombok.EqualsAndHashCode;

@Entity
@Data
@EqualsAndHashCode(callSuper=true, exclude="entries")
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class Feed extends BaseModel {

 private static final long serialVersionUID = 7720285113632455831L;
 
 @Column(length=50)
 private String title;
 
 @Column(length=256)
    private String link;
    
    @Lob
    private String description;
 
    @ManyToMany
    @JoinTable(name="feed_category",
      joinColumns = @JoinColumn(name = "feed_id", nullable=false),
            inverseJoinColumns = @JoinColumn(name = "category_id", nullable=false))
    private Set category;

    @OneToMany(mappedBy="feed")
    private Set entries;
}

package com.glinboy.feader.model;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.JoinColumn;
import javax.persistence.Lob;
import javax.persistence.ManyToOne;

import lombok.Data;
import lombok.EqualsAndHashCode;

@Entity
@Data
@EqualsAndHashCode(callSuper=true, exclude="feed")
public class FeedEntry extends BaseModel {

 private static final long serialVersionUID = -7086809764656937022L;
 
 @Column(length=128)
 private String title;
 
 @Lob
 private String description;
 
 @Column(length=512)
 private String link;
 
 @Column(length=64)
 private String author;
 
 @Column(length=40)
 private String guid;
 
 @ManyToOne
 @JoinColumn(name="feed_id", nullable=false)
 private Feed feed;
}

هیچ نظری موجود نیست:

پست کردن نظر