문제

I am having the following error when committing an Entity. According to error I have to assign an id for the Entity but I am expecting it has to be handled by JPA itself.

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)

I have two Entities having one-to-one relationship.

@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;

Main Class:

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();
}

}

UPDATED:

ServiceAlarmConfEntity is configured as below. and it works.

   @MapsId
   @JoinColumn(name = "service_id", referencedColumnName = "id")
   @OneToOne(optional = false, fetch = FetchType.LAZY)
   private Service service;
도움이 되었습니까?

해결책

The ID is only automatically generated if it's annotated with @GeneratedValue. But it isn't.

EDIT:

As explained in the documentation, the standard and recommended way to have the child entity share the ID of its parent entity is the following:

public class ServiceAlarmConfEntity {
    @Id
    private Integer serviceId;

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

    ...
}
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top