Java 与Hibernate JPA的一对一关系

Java 与Hibernate JPA的一对一关系,java,hibernate,jpa-2.0,java-ee-5,Java,Hibernate,Jpa 2.0,Java Ee 5,提交实体时出现以下错误。根据错误,我必须为实体分配一个id,但我希望它必须由JPA自己处理 Exception in thread "main" javax.persistence.PersistenceException: org.hibernate.id.IdentifierGenerationException: ids for this class must be manually assigned before calling save(): alarm.ServiceAlarmCon

提交实体时出现以下错误。根据错误,我必须为实体分配一个id,但我希望它必须由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;

主要类别:

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;

只有使用
@GeneratedValue
注释ID时,才会自动生成ID。但事实并非如此

编辑:

如中所述,让子实体共享其父实体ID的标准和推荐方法如下:

public class ServiceAlarmConfEntity {
    @Id
    private Integer serviceId;

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

    ...
}

但是这样会不会产生两个单独的ID(一个给父母,一个给孩子)?看起来他想让孩子的ID与父母的ID匹配。是的,会的。OP没有问这个问题。考虑到他使用一个单独的连接列来引用父级,我不明白他为什么想要相同的ID。也就是说,为什么关联被标记为insertable=false对我来说是个谜,因为示例代码正试图插入这样的关联。我们必须等待澄清。你说得对,达莫。子实体ServiceAlarmConfEntity的id必须自动生成。@mmc:我们都理解了。但您希望如何生成它?您希望它像父实体一样具有独立的生成ID,还是希望ServiceAlarmConfEntity与其父服务共享相同的ID?如果是后者,为什么在ServiceAlarmConfEntity中有一个join列,因为主键也是join列?在持久化服务实体时,我希望生成的服务id将自动分配给ServiceAlarmConfEntity的服务id。
public class ServiceAlarmConfEntity {
    @Id
    private Integer serviceId;

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

    ...
}