prilia
prilia

Reputation: 1016

Hibernate, JPA - example manytomany with two tables

I try to use with many to many collection mapping, I hae two tables : TASK and TASKRELATED, every task can has many related tasks and every related task can be in many parent tasks. here is my sql diagram:

enter image description here

Here is my entity :

@Entity
public class Task {

    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    private Long taskId;

    @ManyToMany
    @JoinTable(name = "taskRelated", joinColumns = { @JoinColumn(name = "relatedTaskId") }, inverseJoinColumns = { @JoinColumn(name = "taskId") })
    private Set<Task> relatedTasks = new HashSet<Task>(0);

}

Here is my ropository :

public interface ITaskRepository extends JpaRepository<Task, Long>, 
    QueryDslPredicateExecutor<Task>{
}

This is my code :

Task t = repository.findOne(1L);

This is my data in mysql: task table
enter image description here
taskrelated table
enter image description here

When I do read of task object, there is en error:

    failed to lazily initialize a collection of role: org.Task.relatedTasks, no session or session was closed
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: org.Task.relatedTasks, no session or session was closed
    at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:383)
    at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationExceptionIfNotConnected(AbstractPersistentCollection.java:375)
    at org.hibernate.collection.AbstractPersistentCollection.readSize(AbstractPersistentCollection.java:122)
    at org.hibernate.collection.PersistentSet.size(PersistentSet.java:162)
    at com.github.springtestdbunit.sample.service.UsersServiceTest.testTask(UsersServiceTest.java:63)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:601)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
    at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:74)
    at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:83)
    at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:72)

Please help !

in case of @ManyToMany(fetch=FetchType.EAGER) there is error like this :

 illegal access to loading collection
org.hibernate.LazyInitializationException: illegal access to loading collection
    at org.hibernate.collection.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:366)
    at org.hibernate.collection.AbstractPersistentCollection.read(AbstractPersistentCollection.java:111)
    at org.hibernate.collection.PersistentSet.hashCode(PersistentSet.java:434)
    at org.Task.hashCode(Task.java:36)
    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.PersistentSet.endRead(PersistentSet.java:352)
    at org.hibernate.engine.loading.CollectionLoadContext.endLoadingCollection(CollectionLoadContext.java:261)
    at org.hibernate.engine.loading.CollectionLoadContext.endLoadingCollections(CollectionLoadContext.java:246)
    at org.hibernate.engine.loading.CollectionLoadContext.endLoadingCollections(CollectionLoadContext.java:219)
    at org.hibernate.loader.Loader.endCollectionLoad(Loader.java:1005)
    at org.hibernate.loader.Loader.initializeEntitiesAndCollections(Loader.java:993)

Upvotes: 1

Views: 901

Answers (2)

Learner
Learner

Reputation: 21445

As the exception says you are trying to access the collection elements - relatedTasks after closing the session and Hibernate lazily loads the collection elements by default.

So you need to access the elements within the session or alternatively you can add the fetch type to EAGER

 @ManyToMany(fetch = FetchType.EAGER)

Update:

As per stacktrace for exception - LazyInitializationException: illegal access to loading collection it has:

at org.hibernate.collection.PersistentSet.hashCode(PersistentSet.java:434)
at org.nli.seoweb.domain.Task.hashCode(Task.java:36)

Based on this I am assuming you have overridden the hashCode method in Task entity and this method is trying to access the Set. As Hibernate provides a wrapper class for the Set which is PersistentSet in this case, calling hashCode() internally has a validation that checks if the Set is fully initialized or not and then throw the exception.

So try modifying your Task.hashCode() method and make sure you are not using the Set in it, and see if it fixes the issue.

You can also refer to this post for similar exception.

Upvotes: 1

Kerem YILDIZ
Kerem YILDIZ

Reputation: 70

It cannot initialize the collection, have you tried adding the set without initializing it?:

@ManyToMany
@JoinTable(name = "taskRelated", joinColumns = { @JoinColumn(name = "relatedTaskId") }, inverseJoinColumns = { @JoinColumn(name = "taskId") })
private Set<Task> relatedTasks;

Upvotes: 1

Related Questions