Сложная проблема с сохранением порядка JPA

Я работаю над проектом с некоторыми необычными отношениями сущностей, у меня проблемы с JPA. Есть два важных объекта; User, и давайте назовем другой X. Пользователь имеет отношения "один ко многим" И два "один к одному" с X. В основном это выглядит так

[Пользователь]

@OneToMany(mappedBy="user", cascade=CascadeType.ALL, orphanRemoval=true)  
private List<X> xList;

@OneToOne  
@JoinColumn(name = "active_x1_id")  
private X activeX1;  

@OneToOne  
@JoinColumn(name = "active_x2_id")  
private X activeX2;

[X entity]

@ManyToOne()  
@JoinColumn(name="user_id")  
private User user;

При сохранении нового пользователя я также хочу сохранить две сущности x (одну для activeX1 и одну для activeX2) в одной транзакции. Jpa странно справляется с этой abit, лог выглядит так:

INSERT INTO X VALUES (...) // x1  
INSERT INTO USERS VALUES (...)  
INSERT INTO X() VALUES (...) // x2  
UPDATE USERS SET ...  
UPDATE X VALUES (...) // updates x1  

Это делает невозможным использование ограничений NOT NULL в базе данных. Есть ли лучший способ справиться с этими множественными отношениями? Или способ контролировать, в каком порядке JPA сохраняет объекты? JPA действительно явно пытается работать против меня в этой операции. Любая помощь будет оценена по достоинству.


person Rasmus Franke    schedule 17.12.2010    source источник
comment
Что вы имеете в виду, JPA справляется с этим немного странно? Вы используете конкретную реализацию JPA ... Hibernate? EclipseLink? и именно эта реализация делает то, что вы говорите. Это не значит, что все реализации JPA делают такие вещи.   -  person DataNucleus    schedule 17.12.2010
comment
Вы правы, я имел в виду EclipseLink.   -  person Rasmus Franke    schedule 20.12.2010


Ответы (2)


Почему бы вам просто не использовать аннотацию @NotNull? Я не думаю, что есть способ изменить постоянный порядок. Это нужно делать вручную. Что-то вроде этого,

User user = ...;

if ( user.getActiveX1().getId() == null ) {
      entityManager.persist( user.getActiveX1() );
} else {
      entityManager.merge( user.getActiveX1() );
}

if ( user.getActiveX2().getId() == null ) {
      entityManager.persist( user.getActiveX2() );
} else {
      entityManager.merge( user.getActiveX2() );
}

if ( user.getId() == null ) {
      entityManager.persist( user );
} else {
      entityManager.merge( user );
}
person zinan.yumak    schedule 17.12.2010
comment
По моему опыту, @NotNull имеет эффект только при автоматическом создании базы данных только из нотаций и не действует во время выполнения. Как бы то ни было, мне удалось решить эту проблему с помощью метода очистки EntityManager, подробности см. Ниже. - person Rasmus Franke; 20.12.2010

Решено с использованием метода EntityManager.flush, заставляющего JPA сначала сохранять пользователя.

user.setProperties (свойства);
em.persist (пользователь);
em.flush ();

X x1 = новый X (пользователь);
user.setActiveX1 (x1);
X x2 = новый X (пользователь);
user.setActiveX2 (x2);

Мне все еще нужно разрешить нулевые значения в столбце activeX пользователя, но это нормально, поскольку я могу, по крайней мере, принудительно указать значение не null для X.

person Rasmus Franke    schedule 20.12.2010