2013-06-03 4 views
1

У меня возникает следующая ошибка при совершении сущности. По ошибке я должен назначить идентификатор для Entity, но я ожидаю, что он будет обрабатываться самой JPA.Индивидуальные отношения с Hibernate-JPA

Exception in thread "main" javax.persistence.PersistenceException: org.hibernate.id.IdentifierGenerationException: ids for this class must be manually assigned before calling save(): alarm.ServiceAlarmConfEntity 
    at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1214) 
    at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1147) 
    at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1153) 
    at org.hibernate.ejb.AbstractEntityManagerImpl.persist(AbstractEntityManagerImpl.java:678) 
    at alarm.Test.main(Test.java:32) 
Caused by: org.hibernate.id.IdentifierGenerationException: ids for this class must be manually assigned before calling save(): alarm.ServiceAlarmConfEntity 
    at org.hibernate.id.Assigned.generate(Assigned.java:53) 
    at org.hibernate.event.def.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:121) 
    at org.hibernate.ejb.event.EJB3PersistEventListener.saveWithGeneratedId(EJB3PersistEventListener.java:69) 

У меня есть две организации, имеющие отношения «один-к-одному».

@Entity(name ="services") 
@Table(name = "services") 
public class Service implements Serializable { 
    private static final long serialVersionUID = 1L; 
    @Id 
    @GeneratedValue(strategy = GenerationType.IDENTITY) 
    @Basic(optional = false) 
    @Column(name = "id") 
    private Integer id; 
    @Column(name = "label") 
    private String label; 
    @Column(name = "schemapath") 
    private String schemapath; 
    @Column(name = "customizedPath") 
    private String customizedPath; 
    @Column(name = "birimId") 
    private Integer birimId; 
    @Column(name = "alarmthresholdXML") 
    private String alarmthresholdXML; 
    @OneToOne(cascade = CascadeType.ALL, mappedBy = "service", fetch = FetchType.LAZY) 
    private ServiceAlarmConfEntity serviceAlarmConfEntity; 

@Entity(name ="service_alarm_conf") 
@Table(name = "service_alarm_conf") 
public class ServiceAlarmConfEntity implements Serializable { 
    private static final long serialVersionUID = 1L; 
    @Id 
    @Basic(optional = false) 
    @Column(name = "service_id") 
    private Integer serviceId; 
    @Lob 
    @Column(name = "alarmthresholdXML") 
    private String alarmthresholdXML; 
    @Column(name = "alarmCheckEnable") 
    private Integer alarmCheckEnable; 
    @Column(name = "alarmDataTransferTimeInSeconds") 
    private Integer alarmDataTransferTimeInSeconds; 
    @JoinColumn(name = "service_id", referencedColumnName = "id", insertable = false, updatable = false) 
    @OneToOne(optional = false, fetch = FetchType.LAZY) 
    private Service service; 

Основное Класс:

package alarm; 


import javax.persistence.EntityManager; 
import javax.persistence.EntityManagerFactory; 
import javax.persistence.EntityTransaction; 
import javax.persistence.Persistence; 

public class Test { 

public static void main(String[] args) { 
    EntityManagerFactory emf = Persistence.createEntityManagerFactory("alarm"); 

    EntityManager em = emf.createEntityManager(); 
    EntityTransaction tx = em.getTransaction(); 
    Service service = new Service(); 
    service.setLabel("Test1"); 
    service.setBirimId(16); 
    service.setSchemapath("test1"); 
    service.setCustomizedPath("Test1"); 


    ServiceAlarmConfEntity serviceAlarmConfEntity = new ServiceAlarmConfEntity(); 
    serviceAlarmConfEntity.setAlarmCheckEnable(1); 
    serviceAlarmConfEntity.setAlarmthresholdXML("alarmThresholdXML"); 
    serviceAlarmConfEntity.setService(service); 


    service.setServiceAlarmConfEntity(serviceAlarmConfEntity); 

    tx.begin(); 
    em.persist(service);   
    tx.commit(); 
    em.close(); 
} 

}

ОБНОВЛЕНО:

ServiceAlarmConfEntity сконфигурирован, как показано ниже. и это работает.

@MapsId 
    @JoinColumn(name = "service_id", referencedColumnName = "id") 
    @OneToOne(optional = false, fetch = FetchType.LAZY) 
    private Service service; 

ответ

2

Идентификатор только автоматически, если он помечается @GeneratedValue. Но это не так.

EDIT:

Как объяснена в the documentation, стандартные и рекомендуемый способ иметь доли дочернего объекта идентификатора родительского объекта заключается в следующем:

public class ServiceAlarmConfEntity { 
    @Id 
    private Integer serviceId; 

    @MapsId 
    @OneToOne(optional = false, fetch = FetchType.LAZY) 
    @JoinColumn(name = "service_id") 
    private Service service; 

    ... 
} 
+1

, но тогда это не было бы генерировать два отдельные идентификаторы (один для родителя и один для ребенка)? Похоже, он хочет, чтобы идентификатор ребенка соответствовал идентификатору родителя. – DannyMo

+0

Да, было бы. ОП не спрашивал об этом. И учитывая, что он использует отдельный столбец для ссылки на родителя, я не понимаю, почему он хотел бы идентичные идентификаторы. Тем не менее, почему ассоциация отмечена insertable = false - это загадка для меня, так как пример кода точно пытается вставить такую ​​ассоциацию. Нам придется ждать разъяснений. –

+0

Вы правы дамо. id дочернего объекта Entity ServiceAlarmConfEntity должен генерироваться автоматически. –

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