2013-02-20 4 views
3

У меня есть список объектов. Это объекты JPA «Местоположение».JPA с JTA, как сохранить много entites в одной транзакции

List<Location> locations; 

У меня есть безгосударственный EJB, который проходит через список и сохраняется каждый.

public void createLocations() { 
    List<Locations> locations = getListOfJPAManagedLocationEntities(); // I'm leaving out the details of this because it has nothing to do with the issue 

    for(Location location : locations) { 
     em.persist(location); 
    } 
} 

Код работает нормально. У меня нет никаких проблем. Однако проблема заключается в следующем: я хочу, чтобы это была транзакция «все или ничего». В настоящее время каждый раз через цикл for метод persist() будет вставлять новую строку в базу данных. Предположим, у меня есть 100 объектов местоположения, а у 54-го объекта что-то не так с ним, и возникает исключение. В базу данных будет включено 53 записи. Я хочу: все они должны преуспеть, прежде чем кто-то из них преуспеет.

Я пользуюсь последней версией & самой большой версии Java EE6, EJB 3.x. и JPA 2. В моем persistence.xml используется JTA.

<persistence-unit name="myPersistenceUnit" transaction-type="JTA"> 

И мне нравится иметь JTA. Я не хочу останавливать использование JTA. 90% времени JTA делает именно то, что я хочу, чтобы он делал. Но в этом случае я не вижу.

Мое понимание JTA должно быть неточным, потому что я всегда думал, что начало и конец метода EJB обозначают границы транзакции JTA (предположим, что только один метод включен, как я показал выше). По моей логике транзакция не закончилась до тех пор, пока цикл for не будет выполнен, и метод вернется, а затем в этот момент записи сохраняются.

Я использую драйвер JTDS для SqlServer 2008. Возможно, база данных не хочет вставлять запись, не совершая ее немедленно. Идентификатор объекта определяется следующим образом:

@Id 
@GeneratedValue(strategy = GenerationType.IDENTITY) 

Я проверил спецификации, и это не свойственно вызывать различные «UserTransaction» или «getTransaction()» методы в среде JTA..

Так что я могу сделать? Спасибо.

+0

Итак, в чем проблема? Что произойдет, если 54-я запись приведет к выбросу исключения? Вы сделали тест? Ваши предположения верны: в случае исключения времени выполнения вы будете иметь откат. –

+0

Думаю, я не был достаточно ясен в своем первоначальном вопросе. Я уже тестировал это; снова и снова. Если 54-я запись не удалась, предыдущие 53 записи по-прежнему вставляются в базу данных. Это проблема, потому что я не хочу, чтобы эти 53 записи были вставлены в базу данных. –

+0

Какова 54-я запись? Вызывает ли это исключение? Который из? –

ответ

0

Если вы используете транзакции, управляемые JTA и контейнерами, поведение по умолчанию для вызова метода EJB для сеанса должно выполняться в транзакции (это похоже на аннотирование его @TransactionAttribute(TransactionAttributeType.REQUIRED). Это означает, что ваш код уже выполняется в транзакции и будет делать то, что вы ожидайте: если в строке 54 произойдет исключение, все предыдущие вставленные строки будут откатны. Вы можете продолжить и протестировать его, бросив себе исключение в какой-то момент цикла. Обратите внимание, что если вы выбрали проверенное исключение, объявленное вашим методом вы можете указать, что контейнер должен делать при возникновении этого исключения. Вам необходимо аннотировать класс исключений с помощью @ApplicationException (rollback=true).

+0

Как я уже отмечал выше, я уже тестировал это; много раз. Если 54-я запись не удалась, предыдущие 53 записи по-прежнему вставляются в базу данных. Это проблема, потому что я не хочу, чтобы эти 53 записи были вставлены в базу данных. –

+0

Как вы получаете EntityManager? Если он не вводится, вам нужно будет вызвать joinTransaction или управлять всей транзакцией (начать, откат и т. Д.). Мой совет - использовать транзакции, управляемые контейнерами, и вводить EntityManagers. – Bogdan

+0

EntityManager вводится следующим образом: @PersistenceContext (unitName = "myPersistenceUnit") private EntityManager em; –

0

Если во время цикла повторялась запись, то она будет продолжаться без проблем и когда компилятор rea ches эта строка em.flush(); после цикла, тогда он выкинет исключение и откат транзакции.

0

Я использую JBoss. Установите свой источник данных в вашем файле standalone.xml или domain.xml, чтобы иметь <datasource jta="true" ...> Кажется очевидным, но я, очевидно, неправильно это сделал давно и забыл об этом.

Смежные вопросы