Spring JPA: управляемый приложением контекст персистентности с @Transactional и @PersistenceContext - PullRequest
6 голосов
/ 24 февраля 2011

В настоящее время я испытываю управляемый приложением контекст персистентности, создавая менеджер сущностей вручную и сохраняя их, чтобы включить транзакцию, которая охватывает несколько вызовов (например, расширенный контекст персистенции) в приложении JSE.

Но,Мне интересно, могу ли я избежать отправки объекта entityManager по всему сервису и методам DAO в качестве дополнительного параметра, используя инъекцию пружины @PersistenceContext и пометив методы аннотацией @Transactional, чтобы использовать транзакцию, начатую вручную с этим менеджером сущностей.

Я думаю, что я могу как-то справиться с этим, используя ThreadLocal для этой функции, но я буду счастлив, когда смогу прикрепить это к весенней структуре.

Это пример того, что у меня естьв виду:


Метод действия пользовательского интерфейса:

Здесь мы видим, что транзакция запускается логикой пользовательского интерфейса, поскольку в бэкэнде нет метода фасадов / команд для группировки этихпризывы кбизнес-логика:

Long transactionid = tool.beginTransaction();

// calling business methods
tool.callBusinessLogic("purchase", "receiveGoods", 
                        paramObject1, transactionid);

tool.callBusinessLogic("inventory", "updateInventory", 
                        paramObject2, transactionid);

tool.commitTransaction(transactionid);

Внутри инструмента:

public Long beginTransaction() {
  // create the entity --> for the @PersistentContext
  Entitymanager entityManager = createEntityManagerFromFactory();
  long id = System.currentTimeMillis();
  entityManagerMap.put(id, entitymanager);

  // start the transaction --> for the @Transactional ?
  entityManager.getTransaction().begin();

  return id;
}

public void commitTransaction(Long transactionId) {
  EntityManager entityManager = entityManagerMap.get(transactionId);

  entityManager.getTransaction().commit();
}

public Object callBusinessLogic(String module, String function, 
                        Object paramObject, Long transactionid) {
    EntityManager em = entityManagerMap.get(transactionId);

    // =================================
    //        HOW TO DO THIS????
    // =================================
    putEntityManagerIntoCurrentPersistenceContext(em);

    return executeBusinessLogic(module, function, paramObject, transactionid);
}

И пример метода обслуживания:

public class Inventory {
  // How can i get the entityManager that's been created by the tool for this thread ?
  @PersistenceContext
  private EntityManager entityManager;

  // How can i use the transaction with that transactionId ?
  @Transactional
  public void receiveGoods(Param param) {
    // ........
  }
}

Есть ли способ достичь этого?

Спасибо!

Ответы [ 3 ]

9 голосов
/ 06 июля 2011

Обработка Spring аннотацией @PersistenceContext делает почти именно того, что вам нужно, с одной большой разницей: вы всегда получаете EntityManager в области транзакции, и Spring всегда внедряет один и тот же экземпляр для одного и того же потока, так что у вас есть вид распространения и вам не нужно беспокоиться о безопасности потоков. Но вы никогда не получите расширенный контекст таким образом!
Поверьте мне, Spring 3 и расширенный контекст персистентности плохо сочетаются друг с другом, возможно, это изменится в Spring 3.1, но я боюсь, что это не в их фокусе. Если вы хотите использовать расширенный контекст постоянства, позвольте Spring внедрить EntityManagerFactory (с помощью аннотации @PersistenceUnit), а затем создайте EntityManager самостоятельно. Для распространения вам придется либо передать экземпляр в качестве параметра, либо сохранить его в ThreadLocal самостоятельно.

3 голосов
/ 24 февраля 2012

Действительно, чтобы иметь управляемый приложением контекст персистентности, вам нужно каким-то образом «взломать» инфраструктуру @ Transactional & @ PersistenceContext , предоставив им свою собственную сущностьДиспетчер и не позволяйте Spring создавать свои собственные.

Ключ к достижению этого состоит в том, чтобы немного поиграть с классом TransactionSynchronizationManager , чтобы зарегистрировать свой собственный Entity Manager в локальном потоке, Spring будетиспользуйте его, чтобы внедрить атрибут @ PersistenceContext .

Некоторое время назад я нуждался в этом для своего собственного приложения, и я разработал небольшую архитектуру на основе Spring AOP для управления расширенным постоянством.context.

Подробности здесь: Глобальный диалог JPA / Hibernate с Spring AOP

0 голосов
/ 28 июня 2011

Когда вы конфигурируете свои транзакции через @Transactional, вам следует передать конфигурацию ваших транзакций аннотации.Здесь вы начинаете транзакцию и затем надеетесь, что @Transactional также будет запущен.для получения дополнительной информации лучше начать читать http://static.springsource.org/spring/docs/2.5.x/reference/transaction.html => 9.5.6.Использование @ Transactional

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