2011-04-28 18 views
5

Estoy usando JPA con Spring. Si tuviera que dejar que la primavera manejar las transacciones, entonces esto es lo que se vería mi capa de servicios como asumir el EntityManager se ha inyectado correctamente en los DAOs:Servicio Transaccional Manual y capa DAO para JPA con Spring

MyService { 

    @Transactional 
    public void myMethod() { 
     myDaoA.doSomething(); 
     myDaoB.doSomething(); 
    } 
} 

Sin embargo, si tuviera que hacer transacciones de forma manual, no tengo para asegurarse de pasar esa instancia de EntityManager a cada uno de los DAO dentro de una transacción. ¿Alguna idea de cómo se puede refactorizar mejor? Me pagan feo haciendo MyDaoA (em) nuevo o pasándolos en cada método DAO como doSomething (em).

MyService { 

    private EntityManagerFactory emf; 

    public void myMethod() { 
     EntityManager em = emf.createEntityManager(); 
     EntityTransaction tx = em.getTransaction(); 
     MyDaoA myDaoA = new MyDaoA(em); 
     MyDaoB myDaoB = new MyDaoB(em); 
     try { 
      tx.begin(); 
      myDaoA.doSomething(); 
      myDaoB.doSomething(); 
      tx.commit(); 
     } catch(Exception e) { 
      tx.rollback(); 
     } 
    } 
} 

Respuesta

3

Sin embargo, si tuviera que hacerlo de forma manual transacciones, tengo que asegurarse de que pasar esa instancia de EntityManager en cada uno de los DAOs dentro de una transacción.

Aquí es donde se equivoca. A partir de la primavera de referencia, JPA section:

El problema principal con un DAO tal es que siempre crea un nuevo EntityManager a través de la fábrica. Usted puede evitar esto mediante la solicitud de un EntityManager transaccional (también llamado "EntityManager compartida" porque Es un compartida, delegación flujos seguros para el actual transaccional EntityManager) a inyectar en lugar de la fábrica:

public class ProductDaoImpl implements ProductDao { 

    @PersistenceContext 
    private EntityManager em; 

    public Collection loadProductsByCategory(String category) { 
     Query query = em.createQuery(
         "from Product as p where p.category = :category"); 
     query.setParameter("category", category); 
     return query.getResultList(); 
    } 
} 

La anotación @PersistenceContext tiene un tipo de atributo opcional, que valores predeterminados a PersistenceContextType.TRANSACTION. Este valor predeterminado es lo que necesita para recibir un proxy EntityManager compartido.

+1

todavía estoy claro en cuanto a cómo iba a ir haciendo las transacciones manuales con un servicio y DAO capa. – Langali

+0

a) Probablemente usaría TransactionTemplate o JpaTemplate si tuviera que hacerlo b) no lo haga. Es un dolor. –

+0

Lo sentimos, esto va más allá del alcance de esta pregunta. Lea la referencia de Spring, especialmente las secciones Transaction Management http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/transaction.html y ORM http://static.springsource.org /spring/docs/3.0.x/spring-framework-reference/html/orm.html (sugerencia: la traducción de excepciones es tu amigo) –

1

agregar esto a su configuración de primavera

<bean p:entityManagerFactory-ref="emf" class='org.springframework.orm.jpa.support.SharedEntityManagerBean' /> 

ahora puede @Autowired EntityManager dentro de su DAO

para la gestión de transacciones, puesto que ya el uso de la primavera, y la anotación @Transactional, supongo ya tienes un administrador de transacciones declarado en tu primavera.xml

así que usar la gestión de transacciones de la primavera

como

transactionStatus = platformTransactionManager.getTransaction(new DefaultTransactionDefinition()); 
// do your work here 
platformTransactionManager.commit(transactionStatus); 
Cuestiones relacionadas