2013-08-23 6 views
2

У меня есть две таблицы в базе данных, A и B. Таблица B имеет идентификатор, состоящий из двух полей. Один из них - это внешний ключ для A. Id из A автоматически генерируется при вставке последовательностью.JPA: сохраняющаяся сущность с составным первичным ключом

A: 
    ID (PK) 
    (*other fields*) 

B: 
    SOME_FIELD (PK) 
    A_ID (PK, FK to A) 

Я сопоставляются две таблицы в JPA (Hibernate) следующие JPA specification, таким образом:

@Entity 
@Table(name = "A") 
public class A implements Serializable { 
    @Id 
    @SequenceGenerator(name = "A_SEQ", sequenceName = "A_SEQ") 
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "A_SEQ") 
    @Column(name = "ID") 
    private Long id; 
    (...) 
} 

@Entity 
@Table(name = "B") 
public class B implements Serializable { 
    @EmbeddedId 
    @AttributeOverride(name = "someField", column = @Column(name = SOME_FIELD)) 
    private BPK pk; 

    @MapsId("aId") 
    @ManyToOne 
    @JoinColumn(name = "A_ID") 
    private A a; 
    (...) 
} 

@Embeddable 
public class BPK implements Serializable { 
    private Long aId; 
    private String someField; 

    @Override 
    public boolean equals(Object o) { 
     (...) 
    } 

    @Override 
    public boolean hashCode() { 
     (...) 
    } 

    (...) 
} 

Проблема заключается в том, что, когда я пытаюсь сохранить объект B, призывающую entityManager.persist (б), где ба устанавливается на объект А, который существует уже в базе данных, я получаю исключение:

javax.persistence.PersistenceException: org.hibernate.PersistentObjectException: detached entity passed to persist: package.name.A 

Я не знаю, почему это происходит. Я пытаюсь сохранить объект класса B, а не A. Является ли класс сущности неправильным? Или, может быть, я не должен использовать упорство здесь?

+0

Вам необходимо реализовать 'Serializable' в вашем классе сущности. – iNan

+0

Я реализую это. Я не копировал часть «реализует», потому что я реализую больше интерфейсов и не хочу включать ненужные части в свой код. Обновлен вопрос с помощью «реализует Serializable». – martaj

ответ

3

Возможно, объект A больше не удерживается менеджером объекта. Вы пытались установить B.a со «свежим» экземпляром A?

b.setA(get(b.a)); 
entityManager.persist(b); 

Метод get(b.a) может быть все, что вы обычно используете, чтобы найти сущности А из вашего источника данных, например, entityManager.getReference(A.class, a.id);

+0

Спасибо, это помогает. Но я не понимаю, почему это не работает без такого «обновления». Для других объектов, где присутствует внешний ключ, но не включен в составной первичный ключ, я просто вызываю entityManager.persist, и он работает. Имеет ли значение, что внешний ключ является частью первичного ключа в этом случае? – martaj

+0

Композитные первичные ключи - странный зверь - я боролся с ними в прошлом. Честно говоря, из-за этого я склонен придерживаться простого идентификатора первичного ключа, а затем создаю составной внешний ключ. – KidTempo

+0

Я думаю, что это связано с тем, что вы создаете два объекта (B и BPK), а A является частью обоих этих объектов. Поскольку A (как часть первичного ключа) имеет решающее значение для настойчивости, JPA настаивает на том, что он «свежий». – KidTempo

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