2013-03-15 2 views
2

Если у меня есть эти две сущности:JPA двунаправленной @OneToOne и каскад слияния

@Entity class A { 
    @OneToOne(cascade = CascadeType.MERGE, mappedBy = "a") B b; 
    //getters+setters 
} 
@Entity class B { 
    @OneToOne(cascade = CascadeType.MERGE) A a; 
    //getters+setters 
} 

ли JPA спецификация гарантия это?

A a = new A(); 
B b = new B(); 
a.setB(b); 
b.setA(a); 
A managedA = entityManager.merge(a); 
// after commit, managedA will have a reference to a managed B which JPA implementation will link to managedA instead of original unmanaged A 
Assert.assertTrue(managedA.getB().getA() == managedA); 

Я понимаю, что он работает (по крайней мере, с последними EclipseLink, по крайней мере, иногда), но что спецификация не гарантирует, что.

Контрпримеры/спецификации выдержки приветствуются :-)

ответ

1

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

Актуальную семантику операции слияния можно найти в 3.2.7.1 Слияние отдельных объектов состояния спецификаций JPA окончательный выпуск. Он ведет себя по-разному в зависимости от объекта, который вы ввели, и от текущего контекста персистентности.

Замечание: Сущность становится отсоединенной, как только транзакция завершена, пока вы не используете расширенный контекст сохранения.

Пожалуйста, обратите внимание, что вы должны, как правило, не сравнивать объекты с помощью оператора ==, так как на самом деле это не семантика вы желаете для сравнения объекта (идентичность JVM не равна идентичности бизнес-объекта)

+0

Сравнение == здесь специально. Я хочу точно знать, получаю ли я одну и ту же ссылку. equals() гарантируется спецификацией для этого случая. – ymajoros

+0

3.2.7.1 из спецификации JPA 2 говорит следующее, что, по-видимому, указывает на то, что утверждения в моем вопросе будут гарантированы в конце концов. Как вы думаете? «Если X является сущностью, объединенной с X», с ссылкой на другой объект Y, где cascade = MERGE или cascade = ALL не указывается, тогда навигация по той же ассоциации из X 'дает ссылку на управляемый объект Y 'с тем же постоянным идентификатором, что и Y " – ymajoros

+1

Хорошо, я получил вашу точку с оператором ==. Просто хотел указать на это, потому что многие люди смешивают это. И о вашей цитате: «... такая же стойкая идентичность, как и Y» -> постоянная идентичность! Это не идентичность объекта JVM. Вы не обязательно возвращаете тот же объект. Мой совет - всегда ожидать другого объекта. – bennidi

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