I create only one session factory for the whole progamm and create everytime i want to persist/update/query smth. an new entity manager but i get always an to many connection error. Can anybody give me an adivce? In my point of view it cant be the best solution to increase the number of allowed connections in MySql. I used C3P0 for pooling.
Try using a try-catch-finally template like this whenever calling the EntityManager.
EntityManager em = ... //However you get an em.
try {
em.getTransaction().begin();
// ... Put your persistence code here.
em.getTransaction().commit();
} catch (Exception ex) {
em.getTransaction().rollback();
throw ex;
} finally {
em.close();
}
Related
I try to execute this code
#Transactional
#Controller
public class MyController{
....
#RequestMapping(..)
public String MyMethod(...)
{
....
try {
ao_history_repository.save(new AoHistory(..));
}
catch (DataIntegrityViolationException e) {
System.out.println("history already exist");
}
....
model.addAttribute("...", my_respository.findAoToDetail(id) );
return "...";
}
But when i got duplicate entry Exception i catch it but after i got a other Exception
org.hibernate.AssertionFailure: null id in persistence.AoHistory entry
(don't flush the Session after an exception occurs)
I know that When a ConstraintViolationException is thrown it invalidates the current session but how can i reopen a new session and a new transaction ?
As you write, you need a new transaction. From your code snippet it looks like the simplest thing would be to move #Transactional from the controller to the repository classes. As an alternative, you could add a service layer and move #Transactional there.
A different approach would be to pre-check the entity object before trying to save it in the entity manager, so that exception is never thrown.
I am working in java hibernate and mysql. I want to use transaction settimeout for a payment functionality of application. I just test the code as below for settimeout to work.
Transaction tx = (Transaction) threadTransaction.get();
try {
if (tx == null) {
Session session = (Session) threadSession.get();
session.getTransaction().setTimeout(5);
tx=session.beginTransaction();
try {
Thread.sleep(6000);
} catch (InterruptedException e) {
e.printStackTrace();
}
if(session.getTransaction().isActive()) {
System.out.println("session active");
}
else {
System.out.println("session inactive");
}
threadTransaction.set(tx);
}
}
catch (HibernateException e) {
throw new HibernateException("", e);
}
But it print session active, means the timeout doesnt work. What is the reason? please help !
Hibernate is pretty good at doing nothing as long as nothing needs to be done (efficiency and such). I think that is what your test shows, not that the the timeout is not working for what it was intended to do:
"... ensuring that database level deadlocks and queries with huge result sets are limited by a defined timeout."
Also note that "setTimeout() cannot be called in a CMT bean ..."
Test the transaction timeout with some code that does what the transaction timeout was intended for and I think you'll find it working properly.
I am trying to save to database changes made to a detached entity.
The object of the entity is passed to the function by argument (named as data):
private boolean generate(CommonGameData data) {
boolean result = true;
EntityManager em = HibernateUtil.currentEntityManager();
try {
em.getTransaction().begin();
em.merge(data);
em.flush();
...some changes to data object...
em.persist(data);
em.flush();
em.getTransaction().commit();
} catch (Exception ex) {
...
return false;
}
return true;
}
As I have read if I am using the detached entity, I should call merge first.
But after commit is done successfully, I don't see any changes in database.
Where is the mistake?
As you do not save a new entity (from your comment), you do not need a call to persist().
Also I do not see any reasons to make 'some changes' after calling merge(), so I called merge() after making those changes.
So, try the following:
em.getTransaction().begin();
...some changes to data object...
em.merge(data);
em.flush();
em.getTransaction().commit();
Also very important: if you reuse the EntityManager from the a ThreadLocal variable, you should take care of things like failed past transactions (at least clear it + maybe close it). Also if the bug still persists, try recreating an entityManager.
I wanted to save many entities using Hibernates Session in one call, so i created this code:
public void persistOrUpdateAllTrades(List<Trade> objects) {
EntityManager entityManager = entityManagerFactory.createEntityManager();
Session session = (Session)entityManager.getDelegate();
try {
FlushMode lastFlushMode = session.getFlushMode();
session.setFlushMode(FlushMode.MANUAL);
for(Trade trade: objects) {
if(session.get(Trade.class, trade.getId()) == null){
session.save((Object)trade);
}
}
session.flush();
session.setFlushMode(lastFlushMode);
} catch (Throwable e) {
throw new RuntimeException(e.getMessage(),e);
}
}
It usually works well, but sometimes execution stops/hangs at if(session.get(Trade.class, trade.getId()) == null) and i have no idea why. It doesn't throw any exception, and application doesn't stop. Application uses MySQL server running at localhost. Any hints?
You're not closing the EntityManager. This is leaks resources, most often connections from a connection pool. Eventually the pool has no more connections available, so it just blocks until it gets a connection available (which in your case is never). The quick fix would just be to do a entityManager.close() at the bottom of your method.
i am using the following approach to sole lazy initialization problem in hibernate.Pleas tell me whether it will work or not .
I have to implement my transcation in my persistance layer compulsary due to some reasons.
public class CourseDAO {
Session session = null;
public CourseDAO()
{
this.session = this.session = HibernateUtil.getSessionFactory().getCurrentSession();
}
public Course findByID(int cid){
Course crc = null;
Transaction tx = null;
try {
tx = session.beginTransaction();
Query q = session.createQuery("from Course as course where course.cid = "+cid+" ");
crc = (Course) q.uniqueResult();
//note that i am not commiting my transcation here.Because If i do that i will not be able to
//do lazy fetch
}
catch (HibernateException e)
{
e.printStackTrace();
tx.rollback();
throw new DataAccessLayerException(e);
}
finally
{
}
return crc;
}
}
and in the filter i am using the folling code
session = HibernateUtil.getSessionFactory().getCurrentSession();
if(session.isOpen())
HibernateUtil.getSessionFactory().getCurrentSession().getTransaction().commit();
IS this approach right??
Can it can have any problem
could you explain why do you need to have ur transactions in ur repositories? the problem there is that they are going to be so fine-grained, so you are not gonna get any advantage from the session caching
then you are opening the transaction there but closing it in your filter. what happens if you access multiple repositories in your service? Maybe i am not understanding what you mean but i think you need to re-think the reasons that force you to manage your transactions in your repositories
When do you create you CourseDAO? If it is a singleton bean or something else that lives longer than a page view, it will need to keep a SessionFactory and generate a new Session when it needs one rather than keeping a Session.