Tôi khá mới với JPA và Hibernate (tôi đang học chăm chỉ!) Và tôi đang đấu tranh với một vấn đề mà tôi dường như không thể tìm thấy một giải pháp tầm thường Vì vậy, ở đây nó được.Hibernate: Lazy initialization vs hashcode bị hỏng/bằng conundrum
Tôi có một thực thể mà tựa hồ như sau:
@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);
}
}
Dự án của tôi được thiết lập với Spring JPA, vì vậy tôi có tôi CrudRepository<EntityOne,Long>
tiêm trong một lớp dịch vụ mà có một vài @Transactional
phương pháp và tôi quét các gói miền/dịch vụ của tôi cho JPA và các giao dịch tương ứng.
Một trong các phương pháp dịch vụ gọi phương thức findAll()
của kho và trả về danh sách EntityOne
s. Tất cả mọi thứ hoạt động tốt, trừ khi tôi cố gắng truy cập vào các getter cho two
, mà rõ ràng là ném:
org.hibernate.LazyInitializationException: could not initialize proxy - no Session
tôi nghĩ rằng nó có thể có ích để có đối tượng này được khởi tạo, vì vậy tôi chuyển sang kiểu quyến rũ từ lười biếng để háo hức. Tuy nhiên, nếu tôi làm điều đó tôi nhận được như sau:
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)
//...
Tôi nhìn một thời gian ngắn vào mã nguồn của Hibernate và có vẻ như nó đang cố gắng để đưa EntityOne
đối tượng của tôi trong một bộ trước chìa khóa kinh doanh của họ được khởi tạo. Cách giải thích của tôi có đúng không? Có cách nào để giái quyết vấn đề này không? Tôi đang làm điều gì đó vô cùng ngu ngốc?
Tôi đánh giá cao sự giúp đỡ của bạn
EDIT: Tôi chỉ muốn làm rõ rằng những gì tôi đang cố gắng để hiểu đây là những gì thực tiễn tốt nhất là đặc biệt đối với JPA với Hibernate và. Nếu đây là một POJO đơn giản, tôi có thể làm cho trường nhận dạng cuối cùng (tôi thực sự sẽ làm cho toàn bộ lớp không thay đổi được) và được an toàn. Tôi không thể làm điều này bởi vì tôi đang sử dụng JPA. Vì vậy, các câu hỏi: bạn có vi phạm hợp đồng hashCode và theo cách nào không? Hibernate đối phó với vi phạm này như thế nào? JPA đề nghị cách làm điều này nói chung là gì? Tôi có nên loại bỏ hoàn toàn các bộ sưu tập dựa trên băm và sử dụng các danh sách thay thế không?
Giovanni
Tôi đã thay thế tất cả giá trị ban đầu của 'Set' fields 'quan hệ bằng' new LinkedHashMap()' thay vì 'new HashMap()' và nó bắt đầu hoạt động. Nó có lạ không? –