Reputation: 4130
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.getCurrentSession().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.
Upvotes: 0
Views: 8006
Reputation: 309
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();
Upvotes: 2
Reputation: 691635
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).
Upvotes: 1
Reputation: 24910
If you must use a manual transaction, then get rid of the declarative @Transactional
option at the top.
Upvotes: 1
Reputation: 128769
You're using both declarative and programmatic transaction demarcation. Get rid of the session.beginTransaction()
and related method calls. Only use @Transactional.
Upvotes: 4