I think you should not use the hibernate session transactionnal methods, but let spring do that add this to your spring conf: bean id="txManager" class="org.springframework.orm. BernateTransactionManager"> events) when you set one side of a bidirectionnal relation, and you wish to use the mappedBy side of the relation in the same transaction, set both sides. Bernate will not do it for you before the next tx (when the session is a fresh view from the db state) So to address the point above, either do the save in one transaction, and the loading in another one : public static void main(String args) { // init here (getting dao and transaction template) transactionTemplate.
Execute(new TransactionCallback() { @Override public Object doInTransaction(TransactionStatus status) { // save here } } transactionTemplate. Execute(new TransactionCallback() { @Override public Object doInTransaction(TransactionStatus status) { // list here } } } or set both side: event1. SetUser(user); ... event2.
SetUser(user); ... user. SetEvents(Arrays. AsList(event1,event2)) (Also do not forget to address the code enhancement points above, Set not List, collection typing).
I think you should not use the hibernate session transactionnal methods, but let spring do that. Add this to your spring conf: and then I would modify your test method to use the spring transaction template : public static void main(String args) { // init here (getting dao and transaction template) transactionTemplate. Execute(new TransactionCallback() { @Override public Object doInTransaction(TransactionStatus status) { // do your hibernate stuff in here : call save, list method, etc } } } as a side note, @OneToMany assocations are lazy by default, so you don't need to annotate it lazy.(@*ToMany are LAZY by default, @*ToOne are EAGER by default) EDIT: here is now what is happening from hibernate point of view: open session (with transaction start) save a user and keep it in the session (see the session cache as an entity hashmap where the key is the entity id) save an event and keep it in the session save another event and keep it in the session ... same with all the save operations ... then load all users (the "from Users" query) at that point hibernate see that it has already the object in its session, so discard the one it got from the request and return the one from the session.
Your user in the session does not have its event collection initialized, so you get null. ... Here is some points to enhance your code : in your model, when collection ordering is not needed, use Set, not List for your collections (private Set events, not private List events) in your model, type your collections, otherwise hibernate won't which entity to fetch (private Set events) when you set one side of a bidirectionnal relation, and you wish to use the mappedBy side of the relation in the same transaction, set both sides. Bernate will not do it for you before the next tx (when the session is a fresh view from the db state).
So to address the point above, either do the save in one transaction, and the loading in another one : public static void main(String args) { // init here (getting dao and transaction template) transactionTemplate. Execute(new TransactionCallback() { @Override public Object doInTransaction(TransactionStatus status) { // save here } } transactionTemplate. Execute(new TransactionCallback() { @Override public Object doInTransaction(TransactionStatus status) { // list here } } } or set both side: ... event1.
SetUser(user); ... event2. SetUser(user); ... user. SetEvents(Arrays.
AsList(event1,event2)); ... (Also do not forget to address the code enhancement points above, Set not List, collection typing).
I tried your solution, and I got rid of the Lazy problem - unfortunately, not it does not load any Events at all: user.getEvents() Produces a null pointer (altough I can see in the db and from the first iteration that the user does have events associated). Is it possible that hibernateTemplate. Find doe snot resolve the dependencies?
– Niko Jun 15 '10 at 6:56 I uploaded my test-project with your suggestion already in place. Maybe you can find out whats going on. – Niko Jun 15 '10 at 7:10 updated the answer.
– Thierry Jun 15 '10 at 12:38.
I got here looking for a hint regarding a similar problem. I tried the solution mentioned by Thierry and it didn't work. After that I tried these lines and it worked: SessionFactory sessionFactory = (SessionFactory) context.
GetBean("sessionFactory"); Session session = SessionFactoryUtils. GetSession(sessionFactory, true); TransactionSynchronizationManager. BindResource(sessionFactory, new SessionHolder(session)); Indeed what I'm doing is a batch process that must leverage Spring existings managers/services.
After loading the context and doing some invocations I founded the famous issue "failed to lazily initialize a collection". Those 3 lines solved it for me.
This really did the trick - thanks a lot – Niko Aug 11 '10 at 9:39 Worked for me. Awesome. Thanks.
– ashes999 Jan 24 at 15:49 Fixed it! Though my xml file said so I had to do getBean("wfSessionFactory") instead. Also it could probably use an "unbindResource" call in there at the end (see the answers at the end of the question) – rogerdpack Jul 15 at 22:52.
The issue is that your dao is using one hibernate session but the lazy load of the user. GetName (I assume that is where it throws) is happening outside that session -- either not in a session at all or in another session. Typically we open up a hibernate session before we make DAO calls and don't close it until we are done with all lazy loads.
Web requests are usually wrapped in a big session so these problems do not happen. Typically we have wrapped our dao and lazy calls in a SessionWrapper. Something like the following: public class SessionWrapper { private SessionFactory sessionFactory; public void setSessionFactory(SessionFactory sessionFactory) { this.
BernateTemplate = new bernateTemplate(sessionFactory); } public T runLogic(Callable logic) throws Exception { Session session = null; // if the session factory is already registered, don't do it again if (TransactionSynchronizationManager. GetResource(sessionFactory) == null) { session = SessionFactoryUtils. GetSession(sessionFactory, true); TransactionSynchronizationManager.
BindResource(sessionFactory, new SessionHolder(session)); } try { return logic.call(); } finally { // if we didn't create the session don't unregister/release it if (session! = null) { TransactionSynchronizationManager. UnbindResource(sessionFactory); SessionFactoryUtils.
ReleaseSession(session, sessionFactory); } } } } Obviously the SessionFactory the same SessionFactory that was injected into your dao. In your case, you should wrap the entire listUserWithEvent body in this logic. Something like: public List listUserWithEvent() { return sessionWrapper.
RunLogic(new Callable() { public List call() { List users = hibernateTemplate. Find("from User"); for (User user : users) { System.out. Println("LIST : " + user.getName() + ":"); user.getEvents().size(); } } }); } You will need to inject the SessionWrapper instance into your daos.
Unfortunately I don't really get this to work. Do you mean that you DAOImpl extend the SessionWrapper? And who (in my example) would call runLogic and what would be the Callable?
Maybe its cleaerer when you extend the example and adapt it to the sample code I provided. Also, my question is specific to non-web, because I want to use the same model/daos I use in web also for stand-alone applications (Our data crawlers). – Niko Jun 15 '10 at 7:00 Sorry it was confusing.
I've added a section with a runLogic example. You shouldn't need to change your dao at all. It should be injected with the same SessionFactory injected into the SessionWrapper.
The SessionWrapper then gets injected into the daos. – Gray Jun 15 '10 at 12:35 That's what the spring transaction template is doing. (it's just missing Typing :/) – Thierry Jun 15 '10 at 12:42 The spring transaction template also opens a database transaction right?
We didn't want to have to do that with our session wrapper. – Gray Jun 15 '10 at 13:09 What do you mean open a database tx? It opens a connection to the database, exactly like getting a session from the sessionFactory.
Enabling a transaction is just the fact of setting the autoCommit flag from on to off on the connection. – Thierry Jun 15 '107 at 21:10.
In case of Web application, it is also possible to declare a special Filter in web. Xml, that will do session-per-request: openSessionInViewFilter org.springframework.orm. Support.
OpenSessionInViewFilter openSessionInViewFilter /* After that you can lazyload your data anytime during the request.
Everybody has the same problem with Basically they do not work together and you have to come up with a half baked unsatisfactory solution like session in view or some other bad workaround . Using hibernate template means you can onlydo one operation and have to start up another session just to get the related objects. It is actually simper to forget the object relational mapping and just use jdbc.
Bernate is a terrible technology that causes way more problems than it solves. If you've ever Googled a you know what I mean. This technology apparently doesn't work for anybody without a lot of hand holding.
1 Venting and hating on bernate does not solve the problem. Bernate and Spring garnered wide-spread use because they solve some problems extremely well. – ashes999 Feb 15 at 16:34 Agreeing with ashes999, must likely there is a more elegant solution the problem lies with not knowing out to use the spring orm with hibernate correctly together.As the question is worded it is about hibernate and spring.
Using JDBC is an alternative approach but does not get your the object-related functionality of hibernate. – ddcruver May 12 at 15:39 5 While I understand what the commenters are saying, to anyone that's used a good ORM in another language can instantly see that Spring+Getting it to work is an exercise in frustration as one googles for hours on end trying to figure out how to resolve one issue after another. – RHSeeger May 26 at 0:13.
I cant really gove you an answer,but what I can give you is a way to a solution, that is you have to find the anglde that you relate to or peaks your interest. A good paper is one that people get drawn into because it reaches them ln some way.As for me WW11 to me, I think of the holocaust and the effect it had on the survivors, their families and those who stood by and did nothing until it was too late.