views:

53

answers:

1

If I wanted manage transactions programmatically, what is the difference between starting the transaction by injecting a PlatformTransactionManager vs directly injecting EntityMangerFactory/EntityManager and getting transaction from Entitymanager

public class MyDAO  {
@PersistenceContext(unitName="test") EntityManager em;

JpaTransactionManager txnManager = null;
public void setTxnManager(JpaTransactionManager mgr) {
  txnManager = mgr;
}

public void process(Request request) throws Exception {
  TransactionStatus status =
     txnManager.getTransaction(new DefaultTransactionDefinition());
  try {
     em.persist(request);
     txnManager.commit(status);
  } catch (Exception up) {
     txnManager.rollback(status);
     throw up;
  }
}

As apposed to injecting EntityManager directly

public class MyDAO { @PersistenceContext(unitName="test") EntityManager em;

public void process(Request request) throws Exception {
  EntityTransaction txn = em.getTransaction();
  try {
     em.persist(request);
     txn.commit();
  } catch (Exception up) {
     txn.rollback();
     throw up;
  }
}

where as spring config snippet looks like this

 <beans>
    <bean id="MyDAO" class="com.xyz.app.dao.MyDAO">

    <context:annotation-config />

    <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerE ntityManagerFactoryBean">
        <property name="persistenceUnitName" value="persistence" />
        <property name="dataSource" ref="dataSourceProvider" />
        <property name="jpaVendorAdapter" ref="jpaVendorAdapter" />
    </bean>

    <bean id="transactionManagerJpa" class="org.springframework.orm.jpa.JpaTransactionM anager">
          <property name="entityManagerFactory" ref="entityManagerFactory"/>
    </bean>
 </beans>
+2  A: 

Transaction managers should not be injected into DAOs, because a DAO has no way to tell whether they're one participant in a larger transaction or not.

I think the transaction manager belongs with the service layer, not the persistence layer. The services know about use cases and units of work. They orchestrate other services, DAOs and model objects to fulfill their use cases.

duffymo
Okay, I have two question now --First - if I go for declarative transaction management then I would be annotating my methods in DAO to be @Transactional right. In this case all method calls on the DAO are routed through Transactional proxy, so who is managing the transaction here, I thought Spring is wrapping each method call within the transaction (which is resource local). Why can't the DAO methods written in such a manner that if already existing transaction is available (due to a call from another method in this DAO where transaction is already started) this uses that transaction..?
Vamsi
No, you annotate the service methods to be @Transactional, which are then proxied.
duffymo