I am working on sample of Hibernate4 with Spring 3.1.
In my sample , While i print sessionFactory.getCurrentSession().isOpen() on console it prints
true
But I am facing an exception on
sessionFactory.getCurrentSession().isConnected()
Exception is:
org.hibernate.HibernateException: isConnected is not valid without active transaction
EDIT : I googled more and found following solution
sessionFactory.getCurrentSession().beginTransaction();
sessionFactory.getCurrentSession().isConnected()
But i don't want to write begin transaction maually every time i opearte with session methods like isConnected, get,find , save etc.
What are the other possible solutions for above exception?
What if i place #Transactional on my dao class methods?
Regards,
Arun Kumar
isConnected is rarely used and for normal DAO methods it is not needed. Get/Find/Save will open a Connection and Transaction if needed behind the scene, nothing you have to take care of manually.
Related
I am using Spring Mongo for query from Database. And i try drop index by following code
mongoOperations.indexOps(MY_COLLECTION).dropIndex("rowIndex");
and i get error
Cannot run 'dropIndexes' in a multi-document transaction
How can i fix this error ?
I have fixed this, it happen because i place the code inside method with annotation #Transactional. Example:
#Transactional
void funnyAction(){
mongoOperations.indexOps(MY_COLLECTION).dropIndex("rowIndex");
}
I have fixd by moving the code outside the method
I'm working on a bunch of legacy code written by people before me and I'm confused about a particular kind of setup and wonder if this has ever worked to begin with.
There is a managed bean in spring that has a transactional method.
#Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = Throwable.class)
public boolean updateDraftAndLivePublicationUsingFastDocumentsOfMySite(List<FastDocumentLite> fastDocumentLites, Long mySiteId) throws Exception { ... }
Now inside that method I find new instantiations calling update methods fe:
boolean firstFeed = new MySiteIdUpdate(publishing, siteDao, siteDomainService).update(siteId, fastDocumentLites.get(0).getMySiteId());
From my understanding on IOC this new class isn't managed by spring , it's just a variable in the bean. Now going further inside the update method you see another service gets called.
#Transactional(propagation=Propagation.REQUIRED, rollbackFor=Throwable.class)
public void activateSubdomainForSite(Long siteId, boolean activationOfSite)
So if there is a transaction open it should be propagated into this service. But here is what I don't get if that MySiteIdUpdate object isn't managed by spring does the first transaction move forward to the activateSubdomainForSite method ?? Or is another transaction being opened here. I looked in the logs and I believe it to be the latter but I rather ask the experts for a second oppinion before I proclame this legacy code to be complete rubbish to the project lead. I'm suffering with a StaleStateException somewhere further down the road and I'm hoping this has anything to do with it.
I think the code is correct, and the second #Transactional should reuse the existing transaction.
Because:
1) Spring Transaction handling is done either by Proxies or by AspectJ advices. If it is done by Proxies then it is required that MySiteIdUpdate invoke an instance that is injected (this is what you did). If you use AspectJ, then it should work anyway.
2) The association Transactions to the code that use is done by the Thread, this mean, as long as you "are" in the thread which started the transaction you can use it. (you do not start an new thread, so it should work)
An other way to explain: It is perfect legal when you have some method in your call hierarchy that does not belong to an spring bean. This should not make the transaction handling fail.
I am writing a web application using spring 3 and hibernate 3.5 with JPA.
I am using the following code:
Buy buy = buyDAO.find(buyId);
buy.setNum(getNum());
buyDAO.merge(buy);
The find returns an entity (i see it in debug) but the buyDAO.merge throws the exception stated above.
I know that this exception is thrown only if i use query.getSingleResult() and there is no row in the DB for my query.
I am truly baffled by this, I tried every trick I know. I moved these lines to a different method, i tried using a transaction buy nothing works.
In our java project we are using ORM with hibernate and spring.
I had problems in deleting persistent objects. For example this sample method gets entities by ids and then delete them:
#Transactional
public void remove(List<Long> ids) {
SearchTemplate template = new SearchTemplate();
template.addParameter("milestoneId",ids);
List <InvoiceQueue> items = this.findByCriteria(template);
...
this.delete(items);
}
Method executes Ok without any exception but doesn't actually delete the items from the DB.
Adding the following annotation to the method definition #Transactional(propagation = Propagation.REQUIRES_NEW) solves the problem.
Can anyone explain why it doesn't work with the default propagation type PROPAGATION_REQUIRED.
Thanks in advance.
Environment details :
hibernate.version 3.5.5-Final, spring.version 3.0.5.RELEASE
Really just repeating what #PeterBagyinszki said in his comment, but the reason quite probably is that the transaction within which your delete occurs gets rolled back due to some other part throwing an exception, and all the changes made during the transaction get canceled. With Propagation.REQUIRES_NEW, the delete is done within it's own separate nested transaction. The outcome of the nested transaction (committed or rolled back) won't affect the "outer" transaction and vice versa.
Check your logs to see what is causing the transaction to be rolled back, note that even something like a simple SELECT -query failing with something like NoResultException will cause the transaction to roll back, unless you explicitly state in the #Transactional-annotation it not to roll back on certain exceptions.
I have two models: User and Base.
User model:
http://pastebin.com/WdLzBkHJ
Base model:
http://pastebin.com/tQrEUaSu
At first I want to put your mind on this notation in Base model:
#org.hibernate.annotations.Entity(dynamicInsert=true,dynamicUpdate=true)
It doesn't work (in SQL Debug shown that Hibernate generated queries with using unnecessary columns which in MySQL are configured as nullable). Tell me please why? What am I doing wrong?
And the main problem is there (method in which user uploads base and string in this base inserts in the MySQL table after parsing):
http://pastebin.com/yG3Mapze
Insertation is VERY SLOW. I have file with 70000 string per line and I can't wait until Hibernate insert this string into DB. Maximum I was waiting for 30 minutes and that wasn't the end.
If I'll use raw queries like that:
DB.execute("INSERT INTO bases (user_id,email,password) VALUES (1,'" + email.replaceAll("'", "\'") + "','" + password.replaceAll("'", "\'") + "')");
instead of
b.save();
After that insertation of 70000 strings to DB completes after ~10-20 seconds.
So I can't understand where is the problem and how to fix it?
Also you can see this code above method declaration:
#NoTransaction
If I uncomment it then I'll recieve this exception:
#689mbad1k
Internal Server Error (500) for request POST /checker/uploadnewbase
JPA error
A JPA error occurred (The JPA context is not initialized. JPA Entity Manager automatically start when one or more classes annotated with the #javax.persistence.Entity annotation are found in the application.):
play.exceptions.JPAException: The JPA context is not initialized. JPA Entity Manager automatically start when one or more classes annotated with the #javax.persistence.Entity annotation are found in the application.
at play.db.jpa.JPA.get(JPA.java:22)
at play.db.jpa.JPA.em(JPA.java:51)
at play.db.jpa.JPQL.em(JPQL.java:16)
at play.db.jpa.JPQL.find(JPQL.java:44)
at models.User.find(User.java)
at controllers.Security.getUser(Security.java:30)
at controllers.GlobalController.userStat(GlobalController.java:21)
at play.mvc.ActionInvoker.invoke(ActionInvoker.java:502)
at play.mvc.ActionInvoker.invokeControllerMethod(ActionInvoker.java:476)
at play.mvc.ActionInvoker.invokeControllerMethod(ActionInvoker.java:471)
at play.mvc.ActionInvoker.handleBefores(ActionInvoker.java:320)
at play.mvc.ActionInvoker.invoke(ActionInvoker.java:140)
at Invocation.HTTP Request(Play!)
But in Play manual we can see that:
"If you want to prevent Play from starting any transaction at all, you can annotate the method with #play.db.jpa.NoTransaction.
To prevent transactions for all methods, you can annotate the Controller-class with #play.db.jpa.NoTransaction."
So I have three problems which I described:
About exception in NoTransaction.
About using dynamicInsert = true.
About improving perfomance for Hibernate like if I'll use raw queries.
The problem is the hibernate session, which must be cleared. Otherwise you get problems with memory and performance. You can found some information in http://docs.jboss.org/hibernate/core/3.3/reference/en/html/batch.html. Unfortunately I don't know how to get the HibernateSession. Perhaps you can get the EntityManager and work with it. But my experiences with Hibernate and Batch are really frustrating, so I would recommend to use your raw-solution.