Транзакции JTA фиксируются слишком рано, происходит сбой при использовании ограничений - PullRequest
2 голосов
/ 13 мая 2011

У нас есть приложение Java EE, работающее в Glassfish 3.1, где наши модели JPA (с использованием EclipseLink) организованы следующим образом:

Customer
 -> String firstName
 -> String lastName
 -> Address adress
 -> List<Attribute> attributes
 -> Int age

Address
-> String street
-> Int zip
-> String city

Attribute
 -> String code
 -> String name

Большинство атрибутов, таких как firstName и lastName, являютсяотмечены @Column(nullable=false).Теперь мы делаем:

@Stateless
public class CustomerController {

  @PersistenceContext(unitName = "CustomerService")
  private EntityManager em;

  @EJB
  private AttributeController attributeController;

  public String createCustomer() {
    Customer customer = new Customer();
    customer.firstName = "Hans";
    customer.lastName = "Peter";

    customer.address = new Address();
    customer.adress.street = ...

    customer.attributes = new ArrayList<Attribute>();
    customer.attributes.add(attributeController.getByCode("B"));
    customer.attributes.add(attributeController.getByCode("T"));

    customer.age = 27;

    em.persist(customer);
  }
}

Это работает для небольших классов, таких как приведенный выше, но теперь мы добавили больше объектов, которые относятся к клиенту как атрибуты с @OneToMany и загружаются из других @EJBs как attributeController.

Для "больших" моделей теперь кажется, что транзакция совершается прямо в процессе все еще загрузки связанных объектов, так как мы получаем ERROR: null value in column "age" violates not-null constraint.Поскольку мы используем транзакции, управляемые контейнером JTA, и не установили для @TransactionAttribute значение, отличное от значения по умолчанию REQUIRED, мы не контролируем транзакцию напрямую и понятия не имеем, что здесь происходит.

Есть лиопределенное количество «единиц работы», которые можно получить до совершения коммита?Мы загружаем связанные объекты неправильно?Мы совершили еще одну серьезную ошибку?

Как только мы опускаем ограничения nullable=false, все работает нормально ...

1 Ответ

4 голосов
/ 13 мая 2011

Ваши объекты, вероятно, автоматически очищаются при возникновении запросов. Согласно JavaDocs для FlushModeType:

Когда запросы выполняются в транзакции, если * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *, то если для объекта запроса не задано значение FlushModeType.AUTO, а для контекста постоянства не задано значение AUTO (по умолчанию) и режим сброса для объекта Query не задан параметр, поставщик сохраняемости отвечает за обеспечение всех обновлений до состояния всех сущностей в контексте постоянства , которые потенциально могут повлиять на результат запроса видны для обработки запроса. Реализация поставщика сохраняемости может достичь этого путем сброса этих сущностей в базу данных или каким-либо другим способом. Если установлено значение FlushModeType.COMMIT, влияние обновлений, внесенных в объекты в контексте постоянства, на запросы не указывается.

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

Звучит так, будто вы просто хотите использовать EntityManager.setFlushMode() или Query.setFlushMode(), чтобы установить режим промывки на COMMIT.

...