【问题标题】:One-to-One Relationship with Hibernate-JPA与 Hibernate-JPA 的一对一关系
【发布时间】:2013-06-03 18:32:54
【问题描述】:

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

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

【问题讨论】:

    标签: java hibernate jpa-2.0 java-ee-5


    【解决方案1】:

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

    编辑:

    the documentation 中所述,让子实体共享其父实体 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 中有一个连接列,因为主键也是连接列?
    • 在持久化服务实体时,我希望生成的服务 id 会自动分配 ServiceAlarmConfEntity 的 service_id。
    猜你喜欢
    • 2010-10-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-12
    • 2011-12-15
    • 2016-05-07
    • 1970-01-01
    • 2014-04-21
    相关资源
    最近更新 更多