我有3个实体:Contract,Person和ContractPerson。 ContractPerson是Contract和Person之间的连接表,带有额外的字段,因此我创建了一个单独的实体。
Contract.java:
import lombok.Data;
import javax.persistence.*;
import java.util.HashSet;
import java.util.Set;
@Data
@Entity
@Table (name = "contract")
public class Contract {
@Id
@GeneratedValue
@Column (name = "contract_id")
private Long id;
@Column (name = "contract_ref")
private String ref;
@OneToMany (mappedBy = "contract", fetch = FetchType.LAZY)
private Set<ContractPerson> contractPersons = new HashSet<>();
}
Person.java:
import lombok.Data;
import javax.persistence.*;
@Data
@Entity
@Table (name = "person")
public class Person {
@Id
@GeneratedValue
@Column (name = "person_id")
private Long id;
@Column (name = "formality")
private String formality;
@Column (name = "first_name")
private String firstName;
@Column (name = "last_name")
private String lastName;
@OneToMany (mappedBy = "person", fetch = FetchType.LAZY)
private Set<ContractPerson> contractPersons = new HashSet<>();
}
ContractPerson.java:
import lombok.Data;
import javax.persistence.*;
@Data
@Entity
@Table (name = "contract_person")
public class ContractPerson {
@Id
@GeneratedValue
@Column (name = "contract_person_id")
private Long id;
@Column (name = "description")
private String description;
@ManyToOne
@JoinColumn (name = "id_of_person")
private Person person;
@ManyToOne
@JoinColumn (name = "id_of_contract")
private Contract contract;
}
当我尝试使用Spring Data JPA获得具有特定id的合同时,它会生成这种输入:
2014-12-29 18:02:10.843 DEBUG 1932 --- [qtp745716999-20] e.p.i.CollectionReferenceInitializerImpl : Found row of collection: [xxx.Contract.contractPersons#199]
2014-12-29 18:02:10.843 DEBUG 1932 --- [qtp745716999-20] o.h.e.l.internal.CollectionLoadContext : 1 collections were found in result set for role: xxx.Contract.contractPersons
2014-12-29 18:02:10.843 DEBUG 1932 --- [qtp745716999-20] stractLoadPlanBasedCollectionInitializer : Loading collection: [xxx.Contract.contractPersons#199]
2014-12-29 18:02:10.879 DEBUG 1932 --- [qtp745716999-20] o.h.l.p.e.p.i.ResultSetProcessorImpl : Preparing collection intializer : [xxx.Contract.contractPersons#199]
2014-12-29 18:02:10.879 DEBUG 1932 --- [qtp745716999-20] o.h.l.p.e.p.i.ResultSetProcessorImpl : Starting ResultSet row #0
2014-12-29 18:02:10.879 DEBUG 1932 --- [qtp745716999-20] e.p.i.CollectionReferenceInitializerImpl : Found row of collection: [xxx.Contract.contractPersons#199]
2014-12-29 18:02:10.880 DEBUG 1932 --- [qtp745716999-20] o.h.l.p.e.p.i.ResultSetProcessorImpl : Starting ResultSet row #1
2014-12-29 18:02:10.880 DEBUG 1932 --- [qtp745716999-20] e.p.i.CollectionReferenceInitializerImpl : Found row of collection: [xxx.Contract.contractPersons#199]
2014-12-29 18:02:10.880 DEBUG 1932 --- [qtp745716999-20] o.h.e.l.internal.CollectionLoadContext : 1 collections were found in result set for role: xxx.Contract.contractPersons
etc...
在重复这个日志之后,我有了这个:
2014-12-29 18:25:41.805 WARN 1992 --- [tp2080715589-19] o.h.e.loading.internal.LoadContexts : HHH000100: Fail-safe cleanup (collections) : org.hibernate.engine.loading.internal.CollectionLoadContext@53504a5c<rs=com.mysql.jdbc.JDBC4ResultSet@448cef4b>
2014-12-29 18:25:41.805 WARN 1992 --- [tp2080715589-19] o.h.e.loading.internal.LoadContexts : HHH000100: Fail-safe cleanup (collections) : org.hibernate.engine.loading.internal.CollectionLoadContext@3c4208bf<rs=com.mysql.jdbc.JDBC4ResultSet@55932a51>
2014-12-29 18:25:41.805 WARN 1992 --- [tp2080715589-19] o.h.e.loading.internal.LoadContexts : HHH000100: Fail-safe cleanup (collections) : org.hibernate.engine.loading.internal.CollectionLoadContext@134c5281<rs=com.mysql.jdbc.JDBC4ResultSet@44927753>
2014-12-29 18:25:41.805 WARN 1992 --- [tp2080715589-19] o.h.e.loading.internal.LoadContexts : HHH000100: Fail-safe cleanup (collections) : org.hibernate.engine.loading.internal.CollectionLoadContext@77bc9d0c<rs=com.mysql.jdbc.JDBC4ResultSet@6520ed53>
2014-12-29 18:25:41.805 WARN 1992 --- [tp2080715589-19] o.h.e.loading.internal.LoadContexts : HHH000100: Fail-safe cleanup (collections) : org.hibernate.engine.loading.internal.CollectionLoadContext@7feabc3d<rs=com.mysql.jdbc.JDBC4ResultSet@6a97c953>
2014-12-29 18:25:41.805 WARN 1992 --- [tp2080715589-19] o.h.e.loading.internal.LoadContexts : HHH000100: Fail-safe cleanup (collections) : org.hibernate.engine.loading.internal.CollectionLoadContext@bec8a67<rs=com.mysql.jdbc.JDBC4ResultSet@4e0d0b57>
2014-12-29 18:25:41.805 WARN 1992 --- [tp2080715589-19] o.h.e.loading.internal.LoadContexts : HHH000100: Fail-safe cleanup (collections) : org.hibernate.engine.loading.internal.CollectionLoadContext@5672764e<rs=com.mysql.jdbc.JDBC4ResultSet@1d0c0d57>
2014-12-29 18:25:41.806 WARN 1992 --- [tp2080715589-19] o.h.e.loading.internal.LoadContexts : HHH000100: Fail-safe cleanup (collections) : org.hibernate.engine.loading.internal.CollectionLoadContext@74b52738<rs=com.mysql.jdbc.JDBC4ResultSet@5ee5b357>
如果我删除合同中的链接,则没有错误。
你知道吗?无限循环 ?其他?提前感谢您的帮助。
答案 0 :(得分:0)
@ToString
中的主要问题是,由于@OneToMany
和Person
之间具有Contract
关系,因此它会经历无限循环,如果您对其进行调试,则将可能看到StackOverflowException
被抛在了后面。由于@Data
是方便的快捷方式注释,将@ToString
,@EqualsAndHashCode
,@Getter
/ @Setter
和@RequiredArgsConstructor
的功能捆绑在一起。因此,最好的方法是分别使用这些批注并忽略@ToString
而不是如下使用@Data
:
Contract.java:
import lombok.Data;
import javax.persistence.*;
import java.util.HashSet;
import java.util.Set;
@RequiredArgsConstructor
@EqualsAndHashCode
@Getter
@Setter
@Entity
@Table (name = "contract")
public class Contract {
@Id
@GeneratedValue
@Column (name = "contract_id")
private Long id;
@Column (name = "contract_ref")
private String ref;
@OneToMany (mappedBy = "contract", fetch = FetchType.LAZY)
private Set<ContractPerson> contractPersons = new HashSet<>();
}
Person.java:
import lombok.Data;
import javax.persistence.*;
@RequiredArgsConstructor
@EqualsAndHashCode
@Getter
@Setter
@Entity
@Table (name = "person")
public class Person {
@Id
@GeneratedValue
@Column (name = "person_id")
private Long id;
@Column (name = "formality")
private String formality;
@Column (name = "first_name")
private String firstName;
@Column (name = "last_name")
private String lastName;
@OneToMany (mappedBy = "person", fetch = FetchType.LAZY)
private Set<ContractPerson> contractPersons = new HashSet<>();
}
ContractPerson.java:
import lombok.Data;
import javax.persistence.*;
@RequiredArgsConstructor
@EqualsAndHashCode
@Getter
@Setter
@Entity
@Table (name = "contract_person")
public class ContractPerson {
@Id
@GeneratedValue
@Column (name = "contract_person_id")
private Long id;
@Column (name = "description")
private String description;
@ManyToOne
@JoinColumn (name = "id_of_person")
private Person person;
@ManyToOne
@JoinColumn (name = "id_of_contract")
private Contract contract;
}