Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring + Hibernate: Session management within @Transactional methods

There's a lot of questions here on this topic, but still I'm not clear with the procedure of managing session within the transaction.

Let's assume there's some repo:

@Repository
public class SomeRepository {
    @Autowired
    protected SessionFactory sessionFactory;

    @Transactional
    public void doSomething() throws IOException {
        Session session = getSession();
        List<SomeEntity> someEntities = session.createCriteria(SomeEntity.class).list();
        for (int i = index; i < someEntities.size(); i++) {
            /* Some ops with entities */
            if (i % 100 == 0) {
                session.flush();
                session.clear();
            }
        }
        session.close;
    }

    protected Session getSession() {
        return sessionFactory.openSession();
    }
}

Is this code correct? Do I really need to open and close (and flush and clear) session manually each time the operation is running? May I use getCurrentSession() instead and forget about flushing and closing (cuz I guess transaction may take care about the lifecycle for me)?

like image 606
Dmytro Titov Avatar asked Aug 19 '13 10:08

Dmytro Titov


People also ask

Does @transactional close session?

@Transactional helps you to extend scope of Session . Session is open first time when getCurrentSession() is executed and it is closed when transaction ends and it is flushed before transaction commits. In Spring, If we use getCurrentSession() in non-transactional context we get an exception.

What does @transactional do in hibernate?

The @Transactional annotation is the metadata that specifies the semantics of the transactions on a method. We have two ways to rollback a transaction: declarative and programmatic. In the declarative approach, we annotate the methods with the @Transactional annotation.

How hibernate handle multiple transactions?

Therefore, you can run multiple transactions on the same Hibernate Session, but there's a catch. Once an exception is thrown you can no longer reuse that Session. My advice is to divide-and-conquer. Just split all items, construct a Command object for each of those and send them to an ExecutorService#invokeAll .


1 Answers

No, it's not correct. To get the session associated with the current Spring transaction, you must use sessionFactory.getCurrentSession().

And you should never close the session: that's the job of Spring, which will close it when the transaction commits/rollbacks, or even later in the open-session-in-view pattern is used.

Flushing is generally not necessary, except in the situation described in the Hibernate documentation, and which consists in avoiding increasing the size of the first-level cache when you insert a large number of entities in batch. In your case, it doesn't make sense.

like image 107
JB Nizet Avatar answered Sep 28 '22 05:09

JB Nizet