开发者

Hibernate and Spring Transaction Manager: Transaction Not Successfully Started

开发者 https://www.devze.com 2023-03-29 21:27 出处:网络
I have a Generic Repository with a method named saveList(). The purpose of this method is to take a List and persist it in \"chunks\" of 500 objects. Unfortunately, I\'m getting a \"TransactionExcepti

I have a Generic Repository with a method named saveList(). The purpose of this method is to take a List and persist it in "chunks" of 500 objects. Unfortunately, I'm getting a "TransactionException: Transaction not successfully started" when I get to the commit.

Everything I've seen says that this is a result of the Spring Transaction Manager. Unfortunately, for this particular method, I need to manually control the transaction.

Relevant code is below:

// from generic non-abstract repository
@Transactional
public void saveList(List<T> objectList) {
    Session session = sessionFactory.getCurrentSession();
    Transaction tx = session.beginTransaction();
    int i = 1;
    for (T obj : objectList) {

        session.save(obj);
        //sessionFactory.getCurrentSession().save(obj);
        i++;
        if (i % 500 == 0) {
            session.flush();
            //sessionFactory.getC开发者_如何学运维urrentSession().flush();
        }
    }
    if (!tx.wasCommitted()) {
        tx.commit();
    }
    //sessionFactory.getCurrentSession().getTransaction().commit();
}

Configuration from applicationContext.xml:

<tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true"/>
    <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
    <property name="sessionFactory" ref="sessionFactory" />
</bean>

Any assistance is appreciated.


You're using both declarative and programmatic transaction demarcation. Get rid of the session.beginTransaction() and related method calls. Only use @Transactional.


Use openSession method to get session object and close it when you finished your work. It will work perfectly. For Example

Session session = sessionFactory.openSession();


If you must use a manual transaction, then get rid of the declarative @Transactional option at the top.


I don't really see the point of doing this, since the session is not cleared between the flushes (and will thus need as much memory as if you let Hibernate flush at the end of the transaction), but if you really want to do this, and just want a new transaction just for this method, just annotate the method with

@Transactional(propagation = Propagation.REQUIRES_NEW)

and forget about the Hibernate transaction management.

This will make Spring pause the current transaction (if any), start a new transaction, execute your method and commit/rollback the new transaction, and then resume the paused transaction (if any).

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号