Win a copy of Rust Web Development this week in the Other Languages forum!
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Tim Cooke
  • Campbell Ritchie
  • Ron McLeod
  • Liutauras Vilda
  • Jeanne Boyarsky
Sheriffs:
  • Junilu Lacar
  • Rob Spoor
  • Paul Clapham
Saloon Keepers:
  • Tim Holloway
  • Tim Moores
  • Jesse Silverman
  • Stephan van Hulst
  • Carey Brown
Bartenders:
  • Al Hobbs
  • Piet Souris
  • Frits Walraven

JAVA Illegal attempt to associate a collection with two open sessions. Collection

 
Greenhorn
Posts: 9
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hello, i have this error on a java projet when i try to delete an object. I already tried few thing but it didn't work.
The problem didn't occure when i tried to delete an other object type but i guess the relation was maybe not the same.

The problem is, according to me, maybe related to the DAO astract class or on how managed my classes.
My error message :


Type Rapport d'exception message org.hibernate.HibernateException: Illegal attempt to associate a collection with two open sessions. Collection : [Models.Gisement.listeEquipesGisement#5] description Le serveur a rencontré une erreur interne qui l'a empêché de satisfaire la requête.   exception   javax.persistence.PersistenceException: org.hibernate.HibernateException: Illegal attempt to associate a collection with two open sessions. Collection : [Models.Gisement.listeEquipesGisement#5] BLABLABLABLA



My class "Gisement" is the parent of "Mineraux" and "Gaz" :



My class "Gisement" is the parent of "Mineraux" and "Gaz" :



"Equipe"/Team is a ManyToOne bidirectional relationship with "Gisement". A Team work on 1 Gisement at a time while a Gisement can have multiple Team on it.


My guess is that the problem is either on :
-how i handle the initSessionFactory / AbstractDAO
-how are programmed by classes Equipe/Gisement aka the mapping relation is missing something somewhere.

I tried to find solution online but none worked for me. It seems like i open ongoing session or create a new one if needed. And i close them at the end when i use DAO functionality.
CASCADE seemed to be an issue to but it doesn't look like the issue come from it.
The thing is, DAO work on certain class but on this one (i paused my project because of this error so i could have more) doesn't work.
Because of it, i'm doubtful the problem come from the abstractdao/initsession but i don't trust myself on this.

Happy new year by the way
 
Saloon Keeper
Posts: 24825
172
Android Eclipse IDE Tomcat Server Redhat Java Linux
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Welcome to the Ranch, Fabien!

You are using the old Hibernate and I do not recommend doing that. It's better to use Hibernate JPA.

However, the problem would be the same.

Without reading closely, I can deduce that you are trying to work with a set of objects and you're obtaining more than one Hibernate Session while you work with them. In JPA, this would be EntityManager, But regardless, only one manager can manage a set of Entities at one time. So you need to use the same Session (EntityManager) instance for all operations for that set of Entity objects.

So in short, the message means exactly what it says.
 
Fabien Dupuit
Greenhorn
Posts: 9
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Tim Holloway wrote:Welcome to the Ranch, Fabien!


Hello Tim, i'm not on point and don't understand everything i do.
I'm not using directly JPA but the Hibernate approach : SessionFactory.
Because of it, i don't have entityManager object but SessionFactory.
I have my InitSessionFactory class whose role is to create a SessionFactory object.
Then, each time i create a DAO object like this : GisementDao g = new GisementDao().
It would call AbstractDao and eventualy GisementDao too for custom function.
Now, in this example, i'm trying to delete a "Gisement" object.  I created a simple form that retrieve what the user want and here is which Gisement he want to delete.
In my servlet that retrieve the request, i have this code :


To clarify a bit :
A gisement can have 2 main types : gaz and minerals .
And each one of them can have subtypes but it is only a parameter, not classes.
So it is an inheriting context and the mapping was validated.

At this point, i called AbstractDao. Each time i create an object, it does have his own session. When i'm doing a CRUD operation, first it try to recover the ongoing session and if it doesn't, it create a new one :  




Transaction pass through this function to know what to do when i want to use one :


Then, the delete function :


A DAO implementation is really simple as it doesn't bring any new information :


So each object are using their own session/transaction and closing it every time they use a CRUD function.

To be honest, the InitSessionFactory and AbstractDAO came from 2 differents places and this is from me to make them work together :

I don't think it is good but i don't know if it can create error either.

Maybe it is bad to have multiple SessionFactory even if they only operate on one object at a time ? maybe it is an even worst idea when you have inheritance ? But in my code, i already have inheritence somewhere else and i had no problem.
 
Tim Holloway
Saloon Keeper
Posts: 24825
172
Android Eclipse IDE Tomcat Server Redhat Java Linux
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
The Hibernate people were among the most active architects of JPA. I expect someday that they will abandon the original Hibernate and only keep Hibernate JPA up to date. That's why I don't recommend using the old Hibernate.

I use the Spring Framework to manage the "dirty work" parts of my ORM and they include things like automatic transaction management. So it has been a very long time since I've worked with that stuff directly. But I'm pretty sure that you are doing more work than you should be. For example, I think that there's an option in the ordinary Hibernate Transaction Manager to handle the stuff you are doing manually. I also think there's a way to delete without a find first, but I could be mistaken.

The main thing is that if you're going to have a Session factory and you don't use a session façade to override the close method to return the session to the factory, I think you could break things in strange ways.

Also note that if you are operating with multiple web users, each user is in an independent thread, so if your session factory is at global scope, it needs to provide synchronized services.
 
Fabien Dupuit
Greenhorn
Posts: 9
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Tim Holloway wrote:


Hello, i modified my code so the InitSession class is now a Singleton :  



But i did not have success with it... I did try to write it manualy into a main.class and it worked so i believe the issue is somewhere in the abstract/initsession :
 
Tim Holloway
Saloon Keeper
Posts: 24825
172
Android Eclipse IDE Tomcat Server Redhat Java Linux
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
That's not a true Singleton. It's not thread-safe.

For a thread-safe Singleton factory, the constructor needs to be private and the factory "get" method needs to be synchronized.
 
Fabien Dupuit
Greenhorn
Posts: 9
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Tim Holloway wrote:That's not a true Singleton. It's not thread-safe.

For a thread-safe Singleton factory, the constructor needs to be private and the factory "get" method needs to be synchronized.



You're fast Does what is called "Lazy initialization" (here https://en.wikipedia.org/wiki/Singleton_pattern#Java) is correct ?  
Or i would need this : https://en.wikipedia.org/wiki/Initialization-on-demand_holder_idiom

Lazy initialization :


Holder :


But none are fixing my issue sadly.
 
Marshal
Posts: 74637
335
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Fabien Dupuit wrote:. . . "Lazy initialization" . . . is correct ?  . . .

That example uses double‑checked locking; I think double‑checked locking does work, but it makes the code more complicated than it has to be. Let's have a look at Joshua Bloch's Effective Java (2/e[/i and 3/[i]e] pages 17‑18). The nearest you get to the first implementation in youir Wikipedia link is Bloch's second example. Bloch also points out that the simplest way to create a Singleton is to write a one‑element enum.
Bloch is obviously an Elvis Presley fan; this is, sort of, what his second example looks like:-

Your Wikipedia link wrote:. . . lazy initialization, where the instance is created when the static method is first invoked. . . .

That forgets that the INSTANCE is only instantiated when the class is loaded; if class loading isn't necessary then the INSTANCE won't be created.
I am not convinced that the first example in your Wikipedia link is thread‑safe. I believe (not certain) that = on its own behaves as an atomic operation, but not += and i-- but I am not certain. In which case the addMoreCoin() and deductCoin() methods may be thread‑unsafe.
This link is linked to from your second Wikipedia link. It remindss out that there is a serious performance overhead to synchronisation; I don't know whether a Lock would have a similar overhead.
 
Fabien Dupuit
Greenhorn
Posts: 9
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hello, i tried something new but i end up with an other error that is :

session/entitymanager is closed



What's new basicaly is that i tried to use ThreadLocal. Now, when i try to delete, it some what works but i have periodically this error.  
My code (partially) :



My Crud still follow this pattern :


I don't know if i implemented it right or not. Things are getting a bit too abstract for me :/
 
Tim Holloway
Saloon Keeper
Posts: 24825
172
Android Eclipse IDE Tomcat Server Redhat Java Linux
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Well, if you get a session from the factory, use it, and then close the session, then what do you expect will happen when you get the same session from the factory next time?
 
Fabien Dupuit
Greenhorn
Posts: 9
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi Tim, let's assume i understood what you just said.
When a CRUD operation finish, i use this code :  


Session came from this :

That came from getSession() :


When i close the session, i believe that it end the session but i don't think it update the ThreadLocal variable. So, maybe i have to use remove() or set(null) ?


So when i will be confronted again to this code :


i assume it will actually be null ... so the next lines of code that will be call are going to be :  


But it doesn't seem to work.
What i understand is if i close my session related to the sessionFactory which happen to be linked to the ThreadLocal, i will have to get a new one and update the ThreadLocal with it.
So far, i really appreciated your help and i think we're getting close to a work around to my issue.
 
Tim Holloway
Saloon Keeper
Posts: 24825
172
Android Eclipse IDE Tomcat Server Redhat Java Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Understand that I haven't worked with the old Hibernate in many, many years, so I really don't know those functions. Plus I use Spring Data for the repetitive stuff like getting an EntityManager ("session"), so I don't even code that part any more.

But I think you might be getting some confusion relative to JDBC.

1) In JDBC, you get a Connection, use it, and then close it. If it's raw JDBC connection management, an actual Connection object is created and destroyed and once you close() the Connection, it can no longer be used, but if you get a Connection from a JDBC Connection Pool, the rules are different.

2) A JDBC Pool Connection is actually a façade over the real Connection. It mostly passes method calls down to the actual Connection, except in a few cases. One of them is the close() method. A Pool Connection object doesn't close the actual Connection, it just returns the actual Connection to the Connection Pool for re-use. The Connection itself is still usable, although its façade no longer is.

I think that perhaps you're thinking of your factory like it's a Connection Pool and trying to use it like case 2, above when actually it really is just a way of getting case 1-style "connections" (sessions).
 
Fabien Dupuit
Greenhorn
Posts: 9
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi, i'm stuck on this so i will let it as it is for now. Thanks for your help.
 
Tim Holloway
Saloon Keeper
Posts: 24825
172
Android Eclipse IDE Tomcat Server Redhat Java Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Sorry I could not be more helpful. As I said, not only do I use the newer Hibernate (Hibernate JPA), I use Spring Data to manage it. It makes things much simpler and more reliable.
 
Consider Paul's rocket mass heater.
reply
    Bookmark Topic Watch Topic
  • New Topic