Eclipselink выполняет неожиданную вставку в отношениях «многие к одному» - PullRequest
0 голосов
/ 03 июня 2011

У меня есть очень простые отношения между двумя объектами:

@Entity  
public class A {  

  @ManyToOne(optional = false)  
  @JoinColumn(name="B_ID", insertable=false, updatable=true)  
  private StatusOfA sa; 

  getter+setter  
}

@Entity  
public class StatusOfA {  

  @Id    
  private long id; 

  @Column  
  private String status;  

  getter+setter  
}

В БД есть только ограниченный набор StatusOfA.
Я выполняю обновление для A в транзакции:

@TransactionalAttribute
public void updateStatusOfA(long id) {  
  A a = aDao.getAById(123);  
  if(a != null) {  
    a.getStatusOfA().getId();  //just to ensure that the object is loaded from DB
    StatusOfA anotherStatusOfA = statusOfADao.getStatusOfAById(456);  
    a.setStatusOfA(aontherStatusOfA);  
    aDao.saveOrPersistA(a);  
  }  
}

Метод saveOrPersistA объединяет здесь «a».

Я ожидаю, что Eclipselink выполнит только обновление для 'a', чтобы обновить StatusOfA, но выполняет новую вставку в таблицу StatusOfA.Затем Oracle жалуется из-за уникального нарушения соглашения (StatusOfA, который Eclipselink пытается сохранить, уже существует ...).Здесь нет каскадирования, поэтому проблема не в этом, и Hibernate (в JPA2) ведет себя как исключение.
В том же проекте я уже сделал несколько более сложных отношений, и я действительно удивлен, увидев, что отношения здесь вне работает.
Заранее спасибо за помощь.

Ответы [ 2 ]

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

Допущения: @ Id @ GeneratedValue (стратегии = GenerationType.IDENTITY)


Рассмотрим следующие реализации statusOfADao.getStatusOfAById (456):

1. возвращает объект "прокси" с установленным идентификатором:

 return new StatusOfA(456);

2. возвращает сущность в новой транзакции:

EntityManager em = emf.createEntityManager();em.getTransaction().begin();

StatusOfA o = em.find (StatusOfA.class, 456); // em.getReference (StatusOfA.class, 456); em.getTransaction () фиксации (). возврат o;

3. возвращает отдельную сущность:

    StatusOfA o = em.find(StatusOfA.class,456);//em.getReference(StatusOfA.class,456);
em.detached(o);
return o;

4. возвращает сериализованный десериализованный объект:

return ObjectCloner.deepCopy(em.find(StatusOfA.class,456));

5. возвращает прикрепленный объект:

return em.find(StatusOfA.class,456);

Выводы:

  1. Eclipselink обрабатывает только реализацию N5 как "ожидаемую".
  2. Hibernate обрабатывает все пять реализаций как «ожидаемые».
  3. Нет анализа поведения, совместимого со спецификацией jpa
0 голосов
/ 06 июня 2011

Что делает statusOfADao.getStatusOfAById ()?

Использует ли он тот же контекст постоянства (та же транзакция и EntityManager)?

Вам необходимо использовать один и тот же EntityManager, так как не следует смешивать объекты из разных контекстов персистентности.

Что делает saveOrPersistA? Вызов merge () должен разрешить все правильно, но если вы действительно испортили объекты, может быть сложно объединить все, как вы ожидаете.

Вы объединяете только А или его статус? Попробуйте также установить статус для объединенного результата статуса.

...