Ручное обслуживание транзакций и слой DAO для JPA с Spring - PullRequest
5 голосов
/ 28 апреля 2011

Я использую JPA с Spring.Если бы я позволил Spring обработать транзакции, то мой сервисный слой выглядел бы так, если бы EntityManager был правильно введен в DAO:

MyService {

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

Однако, если бы я делал транзакции вручную,Я должен обязательно передать этот экземпляр EntityManager в каждый из DAO в транзакции.Любая идея, как это может быть лучше рефакторинг?Я чувствую себя ужасно, делая новые MyDaoA (em) или передавая их в каждый метод DAO, например, 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();
       }
    }
}

Ответы [ 3 ]

3 голосов
/ 28 апреля 2011

Однако, если бы мне пришлось выполнять транзакции вручную, я должен обязательно передать этот экземпляр EntityManager в каждый из DAO в транзакции.

Здесь вы находитесьнеправильно.Из Spring Reference, JPA section :

Основная проблема с таким DAO состоит в том, что он всегда создает новый EntityManager через фабрику. Этого можно избежать, запросив транзакционный EntityManager (также называемый «разделяемым EntityManager», потому что это общий, потокобезопасный прокси-сервер для фактического транзакционного EntityManager), а не фабрикой:

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(); 
    }
}

Аннотация @PersistenceContext имеет необязательный тип атрибута, который по умолчанию равен PersistenceContextType.TRANSACTION.По умолчанию это то, что вам нужно для получения общего прокси EntityManager .

1 голос
/ 28 апреля 2011

добавьте это в свой весенний конфигПредположим, у вас уже есть один менеджер транзакций, объявленный в вашем spring.xml

, поэтому используйте управление транзакциями Spring

как

transactionStatus = platformTransactionManager.getTransaction(new DefaultTransactionDefinition());
// do your work here 
platformTransactionManager.commit(transactionStatus );
0 голосов
/ 28 апреля 2011

Выстрел в темноте немного, я думаю, но знаете ли вы, что можете сделать:

TransactionInterceptor.currentTransactionStatus (). SetRollbackOnly ();

Это обычноисключает большинство случаев, когда вы хотите / должны использовать программные транзакции в системе, в которой в противном случае были бы декларативные транзакции.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...