我对JPA和Hibernate相当陌生(尽管我正在努力学习!),我正在努力解决一个问题,我似乎无法找到一个简单的解决方案,所以在这里。休眠:懒惰初始化vs破碎哈希码/等于难题
我有一个看起来有点像一个实体如下:
@Entity
@Table(name = "mytable1")
public class EntityOne {
// surrogate key, database generated
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private Long id;
// business key
@Column(name = "identifier", nullable = false, unique = true)
private String identifier;
@ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.REFRESH)
@JoinColumn(name = "twoId", nullable = false)
private EntityTwo two;
@OneToMany(mappedBy = "entityOne", fetch = FetchType.EAGER,
cascade = {CascadeType.ALL}, orphanRemoval = true)
private Set<EntityThree> resources = new HashSet<>();
// getters/setters omitted
@Override
public int hashCode() {
// the business key should always be defined (through constructor/query)
// if this is null the class violates the general hashcode contract
// that the integer value returned must always be the same
Assert.notNull(identifier);
// a dirty alternative would be:
// if(identifier==null) return 0;
return identifier.hashCode();
}
@Override
public boolean equals(Object o) {
return o instanceof ResourceGroup
&& ((ResourceGroup) o).identifier.equals(identifier);
}
}
我的项目是建立与Spring JPA,所以我有我的CrudRepository<EntityOne,Long>
在具有几@Transactional
方法和我扫描服务类注射我的域名/服务包分别用于JPA和交易。
其中一个服务方法调用存储库的findAll()
方法并返回一个EntityOne
s的列表。
org.hibernate.LazyInitializationException: could not initialize proxy - no Session
我想这可能是有这个对象初始化非常有用,所以我切换取类型从懒渴望:除非我尝试访问getter方法two
,这显然会抛出一切工作正常。但是,如果我这样做,我得到如下:
java.lang.IllegalArgumentException: [Assertion failed] - this argument is required; it must not be null
at org.springframework.util.Assert.notNull(Assert.java:112)
at org.springframework.util.Assert.notNull(Assert.java:123)
at my.pkg.domain.EntityOne.hashCode(ResourceGroup.java:74)
at java.util.HashMap.hash(HashMap.java:351)
at java.util.HashMap.put(HashMap.java:471)
at java.util.HashSet.add(HashSet.java:217)
at java.util.AbstractCollection.addAll(AbstractCollection.java:334)
at org.hibernate.collection.internal.PersistentSet.endRead(PersistentSet.java:346)
at org.hibernate.engine.loading.internal.CollectionLoadContext.endLoadingCollection(CollectionLoadContext.java:243)
at org.hibernate.engine.loading.internal.CollectionLoadContext.endLoadingCollections(CollectionLoadContext.java:233)
at org.hibernate.engine.loading.internal.CollectionLoadContext.endLoadingCollections(CollectionLoadContext.java:209)
at org.hibernate.loader.Loader.endCollectionLoad(Loader.java:1149)
//...
我简单看了一下Hibernate的源代码,它看起来像它试图把我EntityOne
对象在一组其业务重点初始化之前。我的解释是否正确?有没有解决的办法?我做了一件令人难以置信的事情吗?
我感谢你的帮助
编辑:我只是想澄清,我想在这里了解什么是最好的做法是专门相对于JPA和Hibernate。如果这是一个普通的POJO,我可以使标识符字段最终(我实际上使整个类不可变)并且是安全的。我无法这样做,因为我使用的是JPA。所以问题:你是否违反了hashCode合同,并以哪种方式? Hibernate如何处理这种违规行为? JPA推荐的做法是什么?我应该完全摆脱基于哈希的集合,并使用列表来代替?
Giovanni
我用'new LinkedHashMap()'代替'new HashMap()'代替了我所有的关系'Set'字段'初始值,它开始工作。这不奇怪吗? –