JPA 를
@ManyToMany
를 사용을 하다 보면 인피니티 루프가 발생을 한다.
근데 무작정 발생을 하는 것은 아니고양뱡향성
매핑을 할때 발생을 한다.
@OneToMany
,@ManyToOne
등 ... 어노테이션 매핑을 할때 발생이 된다.
java.lang.StackOverflowError: null
at java.base/java.time.temporal.ValueRange.isValidIntValue(ValueRange.java:295) ~[na:na]
at java.base/java.time.temporal.ValueRange.checkValidIntValue(ValueRange.java:329) ~[na:na]
at java.base/java.time.temporal.ChronoField.checkValidIntValue(ChronoField.java:736) ~[na:na]
at java.base/java.time.LocalDate.ofEpochDay(LocalDate.java:369) ~[na:na]
at java.base/java.time.LocalDateTime.ofEpochSecond(LocalDateTime.java:422) ~[na:na]
at java.base/java.time.format.DateTimeFormatterBuilder$InstantPrinterParser.format(DateTimeFormatterBuilder.java:3418) ~[na:na]
at java.base/java.time.format.DateTimeFormatterBuilder$CompositePrinterParser.format(DateTimeFormatterBuilder.java:2345) ~[na:na]
at java.base/java.time.format.DateTimeFormatter.formatTo(DateTimeFormatter.java:1846) ~[na:na]
at java.base/java.time.format.DateTimeFormatter.format(DateTimeFormatter.java:1820) ~[na:na]
at java.base/java.time.Instant.toString(Instant.java:1329) ~[na:na]
at com.fasterxml.jackson.datatype.jsr310.ser.InstantSerializerBase.serialize(InstantSerializerBase.java:106) ~[jackson-datatype-jsr310-2.11.3.jar:2.11.3]
at com.fasterxml.jackson.datatype.jsr310.ser.InstantSerializerBase.serialize(InstantSerializerBase.java:40) ~[jackson-datatype-jsr310-2.11.3.jar:2.11.3]
at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:728) ~[jackson-databind-2.11.3.jar:2.11.3]
at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:755) ~[jackson-databind-2.11.3.jar:2.11.3]
at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:178) ~[jackson-databind-2.11.3.jar:2.11.3]
at com.fasterxml.jackson.databind.ser.std.CollectionSerializer.serializeContents(CollectionSerializer.java:145) ~[jackson-databind-2.11.3.jar:2.11.3]
at com.fasterxml.jackson.databind.ser.std.CollectionSerializer.serialize(CollectionSerializer.java:107) ~[jackson-databind-2.11.3.jar:2.11.3]
at com.fasterxml.jackson.databind.ser.std.CollectionSerializer.serialize(CollectionSerializer.java:25) ~[jackson-databind-2.11.3.jar:2.11.3]
at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:728) ~[jackson-databind-2.11.3.jar:2.11.3]
at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:755) ~[jackson-databind-2.11.3.jar:2.11.3]
at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:178) ~[jackson-databind-2.11.3.jar:2.11.3]
at com.fasterxml.jackson.databind.ser.std.CollectionSerializer.serializeContents(CollectionSerializer.java:145) ~[jackson-databind-2
주로 DTO 를 바꾸어서 받거나 json 직렬화에서 속성을 없에 버린다.
@JsonIdentityInfo
이번에는 이 어노테이션을 사용해서 해결을 해보려고 한다.
주의 jackson 2.0 이상 부터 사용이 가능하다.
@Data
@Table(name = "app_group")
@Entity
@NoArgsConstructor
@JsonIdentityInfo(generator = ObjectIdGenerators.IntSequenceGenerator.class, property = "id")
public class Group extends AppBaseEntity implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "group_title", nullable = false)
private String title;
@Column(name = "use_yn" , nullable = false)
private Boolean useYn;
@ManyToMany(mappedBy = "groups")
private Set<User> users = new HashSet<>();
@PrePersist
public void onPrePersist(){
if(BooleanUtils.isNotTrue(this.useYn)){
this.useYn = Boolean.FALSE;
}
}
}
ObjectIdGenerators.class 를 어노테이션에 상속을 받아서 사용을 한다.
IntSequenceGenerator
=> id 값이 number
StringIdGenerator
=> id 값이 UUID 형태일때 사용을 하면된다.