【问题标题】:Problems inserting many-to-one row in Hibernate with Oracle在使用 Oracle 的 Hibernate 中插入多对一行时出现问题
【发布时间】:2014-07-11 20:38:15
【问题描述】:

我在使用 Hibernate 4.3.5 将父记录和关联的子记录插入 Oracle 11g 数据库时遇到问题。我有一个包含一组 Image 对象的 Record 类。

记录类映射:

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
    <class name="com.wts.service.model.Record" table="RECORDS">
        <id name="recordId" type="long">
            <column name="REC_ID" precision="10" scale="0"/>
            <generator class="sequence"><param name="sequence">RECORDS_SEQ</param></generator>
        </id>
        ...
        <set name="images" inverse="true" cascade="all">
            <key column="IMG_REC_ID"/>
            <one-to-many class="com.wts.service.model.Image"/>
        </set>
    </class>
</hibernate-mapping>

图像类映射:

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
    <class name="com.wts.service.model.Image" table="IMAGES">
        <id name="imageId" type="long">
            <column name="IMG_ID" precision="10" scale="0"/>
            <generator class="sequence"><param name="sequence">IMAGES_SEQ</param></generator>
        </id>
        <many-to-one name="record" column="IMG_REC_ID" not-null="true"/>
    </class>
</hibernate-mapping>

当我在记录中调用session.save()时,我收到以下错误:

 java.sql.SQLIntegrityConstraintViolationException: ORA-01400: cannot insert NULL into ("IMAGES"."IMG_REC_ID")

我遵循bidirectional one-to-many hibernate association guide 和许多不同的变体,但我永远无法让 Hibernate 将 Record 的主键插入到 Image 的外键列中!这是一个非常简单的关联(也是常见的用例),所以我必须在这里做一些事情。有谁知道我在这里做错了什么??

编辑:

我也尝试将键设置为非空,但我得到了同样的错误:

<set name="images" inverse="true" cascade="all">
        <key column="IMG_REC_ID" not-null="true"/>
        <one-to-many class="com.wts.service.model.Image"/>
    </set>

另外,作为旁注,当我没有设置 inverse="true" 时,我可以让它工作。以下代码有效(Record 和 Image(s) 被持久化到数据库中),但 Images 对象无法拥有多对一关联集:

<set name="images" inverse="false" cascade="all">
        <key column="IMG_REC_ID" not-null="true"/>
        <one-to-many class="com.wts.service.model.Image"/>
    </set>

编辑 2:

这是我调用session.save() 的代码。图像已经与记录相关联,并通过 REST Web 服务 POST 填充。记录和图像以前没有保留。

public void createRecord(Record record) {
        //set the create bys for the images and actions
        record.setCreateDt(new Date());

        for (Image image : record.getImages()) {
            image.setCreateBy(record.getCreateBy());
            image.setCreateDt(record.getCreateDt());
        }
        for (Action action : record.getActions()) {
            action.setCreateBy(record.getCreateBy());
            action.setCreateDt(record.getCreateDt());
        }
        session.save(record);
    }

下面是session.commit()之后运行的sql语句:

14:43:06,586 INFO  [stdout] (http--0.0.0.0-8080-1) Hibernate: select RECORDS_SEQ.nextval from dual
14:43:06,715 INFO  [stdout] (http--0.0.0.0-8080-1) Hibernate: select IMAGES_SEQ.nextval from dual
14:43:06,847 INFO  [stdout] (http--0.0.0.0-8080-1) Hibernate: insert into RECORDS (REC_EXT_ID, REC_GRP_ID, REC_APPL, REC_LATITUDE, REC_LONGITUDE, REC_PRIVATE, REC_LOCKED, REC_CREATE_BY, REC_CREATE_DT, REC_UPDATE_BY, REC_UPDATE_DT, REC_ID) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
14:43:06,969 INFO  [stdout] (http--0.0.0.0-8080-1) Hibernate: insert into IMAGES (IMG_REC_ID, IMG_STATUS, IMG_CT_CD, IMG_FORMAT, IMG_WIDTH, IMG_HEIGHT, IMG_IMAGE, IMG_CREATE_BY, IMG_CREATE_DT, IMG_ID) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
14:43:08,090 WARN  [org.hibernate.engine.jdbc.spi.SqlExceptionHelper] (http--0.0.0.0-8080-1) SQL Error: 1400, SQLState: 23000
14:43:08,090 ERROR [org.hibernate.engine.jdbc.spi.SqlExceptionHelper] (http--0.0.0.0-8080-1) ORA-01400: cannot insert NULL into ("FOSUSER"."IMAGES"."IMG_REC_ID")

【问题讨论】:

    标签: java oracle hibernate hibernate-mapping


    【解决方案1】:

    这不是Hibernate的问题,它是一个json反序列化正常操作jackson,当对象来自rest服务并使用jackson反序列化时,只需将@JsonManagedReference注释设置为父实体中的子属性并设置@JsonBackReference子实体中父属性的注释。在你的情况下:

    public class Record {
    
        @JsonManagedReference
        List<Image> images;
    
    }
    public class Image {
    
        @JsonBackReference
        Record record;
    
    }
    

    【讨论】:

      【解决方案2】:

      看起来您已将图像实体添加到记录的图像集合中,但没有为此图像实体设置记录。像这样:

      Image img = new Image();
      Record rec = new Record();
      rec.getImages().add(img);
      // img.setRecord(rec);    Looks like this is missing in your code
      session.save();
      

      在这种情况下,在图像实体持久化期间,hibernate 会尝试将 null 插入到不可为空的字段中。

      更新。

      请为多对一元素添加类属性。并删除 not-null="true":

      <many-to-one name="record" column="IMG_REC_ID" class="Record"/>
      

      【讨论】:

      • 查看编辑 2。图像已经与记录相关联,因为记录对象来自 REST Web 服务 POST。
      • 从提供的示例中,我看到只有图像实体与适当的记录实体相关联。但反之亦然。每个实体的 image.getRecord() 中存储了什么?
      • 所以,看起来问题是我没有用图像设置记录!在一位同事的建议下,我尝试过一次,但它导致了另一个错误,我没有仔细观察并认为这是同一个问题。看起来现在我必须弄清楚如何让 JBoss 的 REST 提供程序不进入序列化图像和记录的无限循环!再次感谢!
      【解决方案3】:

      这是一个双向的多对一关联。 在记录类映射中,您将错误的列映射为 KEY COLUMN

      将 IMG_REC_ID 替换为 REC_ID

      注意:键列必须是相同的类主键 ID。

      【讨论】:

      • 我用 REC_ID 替换了 KEY COLUMN,但这不起作用(同样的错误)。 IMG_REC_ID 是 IMAGES 表中的 FK 到 RECORDS 表中的 REC_ID PK。那个KEY COLUMN不是应该引用子表中的FK列吗?
      • 尝试使用 cascade="all-delete-orphan" 并在 KEY 中包含“not-null”。
      猜你喜欢
      • 2023-02-04
      • 2021-12-09
      • 1970-01-01
      • 1970-01-01
      • 2018-12-07
      • 1970-01-01
      • 2017-04-27
      • 1970-01-01
      • 2019-06-25
      相关资源
      最近更新 更多