【问题标题】:child collection is not updating in hibernate with cascade all?子集合没有在休眠状态下更新全部级联?
【发布时间】:2017-05-23 15:33:44
【问题描述】:

我有两个表 - 学生和地址。他们有一对多的关系。学生实体正在收集地址实体。当我更新学生的地址集合时。它没有更新数据并给出此错误。当我用子集合更新父实体时,它的下一个键是不在数据库中的递增键。 -

Exception in thread "main" org.hibernate.exception.ConstraintViolationException: could not execute statement
    at org.hibernate.exception.internal.SQLStateConversionDelegate.convert(SQLStateConversionDelegate.java:129)
    at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:49)
    at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:124)
    at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:109)
    at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:189)
    at org.hibernate.engine.jdbc.batch.internal.NonBatchingBatch.addToBatch(NonBatchingBatch.java:59)
    at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3079)
    at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3521)
    at org.hibernate.action.internal.EntityInsertAction.execute(EntityInsertAction.java:88)
    at org.hibernate.engine.spi.ActionQueue.execute(ActionQueue.java:395)
    at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:387)
    at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:303)
    at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:349)
    at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:56)
    at org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1195)
    at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:404)
    at org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction.beforeTransactionCommit(JdbcTransaction.java:101)
    at org.hibernate.engine.transaction.spi.AbstractTransactionImpl.commit(AbstractTransactionImpl.java:175)
    at com.HibernateExample.test.HibernateTest.main(HibernateTest.java:51)


Caused by: org.postgresql.util.PSQLException: ERROR: insert or update on table "address" violates foreign key constraint "student_fk"
  Detail: Key (id)=(5) is not present in table "student".
    at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2476)
    at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:2189)
    at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:300)
    at org.postgresql.jdbc.PgStatement.executeInternal(PgStatement.java:428)
    at org.postgresql.jdbc.PgStatement.execute(PgStatement.java:354)
    at org.postgresql.jdbc.PgPreparedStatement.executeWithFlags(PgPreparedStatement.java:169)
    at org.postgresql.jdbc.PgPreparedStatement.executeUpdate(PgPreparedStatement.java:136)
    at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:186)
    ... 14 more

学生.java

public class Student {

    public int id;
    public String firstName;
    public String lastName;
    public int age;
    public Set<Address> address = new HashSet<>(0);

    public Set<Address> getAddress() {
        return address;
    }
    public void setAddress(Set<Address> address) {
        this.address = address;
    }
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getFirstName() {
        return firstName;
    }
    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }
    public String getLastName() {
        return lastName;
    }
    public void setLastName(String lastName) {
        this.lastName = lastName;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }

}

地址.java

public class Address {

    public int id;
    public String streetName;
    public String cityName;
    public String stateName;
    public String plotNo;
    public Student student;
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getStreetName() {
        return streetName;
    }
    public void setStreetName(String streetName) {
        this.streetName = streetName;
    }
    public String getCityName() {
        return cityName;
    }
    public void setCityName(String cityName) {
        this.cityName = cityName;
    }
    public String getStateName() {
        return stateName;
    }
    public void setStateName(String stateName) {
        this.stateName = stateName;
    }
    public String getPlotNo() {
        return plotNo;
    }
    public void setPlotNo(String plotNo) {
        this.plotNo = plotNo;
    }
    public Student getStudent() {
        return student;
    }
    public void setStudent(Student student) {
        this.student = student;
    }

}

HibernateTest.java

public class HibernateTest {

    public static void main(String[] args) {

        Configuration configuration = new Configuration();
        configuration.configure("hibernate-cfg.xml");
        @SuppressWarnings("deprecation")
        SessionFactory sessionFactory = configuration.buildSessionFactory();

        Session session =   sessionFactory.openSession();
        session.setFlushMode(FlushMode.COMMIT);

        System.out.println(session.getFlushMode().name());

        Transaction transaction = session.beginTransaction();

        Student  student =  (Student) session.get(Student.class, 3);


        Address address = new Address();
        address.setStateName("Kerala");
        address.setCityName("Old Delhi");
        address.setStreetName("Uttaam Nagar");
        address.setPlotNo("158A");

        address.setStudent(student);
        student.getAddress().add(address);
        session.update(student);
        transaction.commit();
        session.close();

        sessionFactory.close();

    }   
}

地址.hbm.xml

<hibernate-mapping>
   <class name="com.HibernateExample.entity.Address" table="address">
      <meta attribute="class-description">
         This class contains the address detail. 
      </meta>
      <id name="id" type="int" column="id">
         <generator class="increment" />
      </id>
      <property name="streetName" column="street_name" type="string"/>
      <property name="cityName" column="city_name" type="string"/>
      <property name="stateName" column="state_name" type="string"/>
      <property name="plotNo" column="plot_no" type="string"/>

      <many-to-one name="student" class="com.HibernateExample.entity.Student" >
            <column name="student_id" not-null="true"></column>
      </many-to-one> 

   </class>
</hibernate-mapping>

学生.hbm.xml

<hibernate-mapping>
   <class name="com.HibernateExample.entity.Student" table="student">
      <meta attribute="class-description">
         This class contains the student detail. 
      </meta>
      <id name="id" type="int" column="id">
         <generator class="increment" />
      </id>
      <property name="firstName" column="first_name" type="string"  length="40" />
      <property name="lastName" column="last_name" type="string" length="40" />
      <property name="age" column="age" type="int"/>

      <set name="address" cascade="all">
         <key column="student_id"/>
         <one-to-many class="com.HibernateExample.entity.Address"/>
      </set>
   </class>
</hibernate-mapping>

【问题讨论】:

  • 尝试在您的实体中覆盖等号和哈希码。
  • 无法复制。复制您的文件 + 配置的 hibernate.cfg。按预期工作。也许您可以分享完整的示例代码以进行重现?
  • 这应该在映射文件中,但在顶部,否则它如何识别 hibernate-mapping 标签 射 DTD 3.0//EN" "hibernate.org/dtd/hibernate-mapping-3.0.dtd">
  • @J-Alex....我可以和你分享吗??
  • @AnkitGoel ...它就在那里....我只是没有在这里添加...。没有它们我的代码将如何工作

标签: java hibernate hibernate-mapping


【解决方案1】:

Session javadoc 开始,Session.update() 被指定与一个分离的 实体实例一起工作。 “如果存在具有相同标识符的持久实例,则会引发异常。”具体哪个异常没有指定,级联可能会将其发送到复杂的代码路径,这可能会导致此错误。

你修改的Student对象不是分离的,而是持久的,因为你是从Session加载得到的,并没有关闭@987654325 @ 或做任何其他会分离它的事情。这意味着对它的所有修改都会自动保存到数据库中,无需手动调用Session。这是在 Session 的类 javadoc 中指定的,带有语句“在刷新时检测到对持久实例的更改并导致 SQL 更新。”

只需删除session.update(student);这一行,我想你的代码就会开始工作了,包括在提交事务时通过级联关系保存新地址。

我已经有一段时间没有使用级联了,所以我不完全确定,但您可能还需要在关系的另一端设置级联。

【讨论】:

  • @AmitDas 删除更新调用并将 cascade=all 添加到地址映射文件?如果这两个都不能解决它,我想我需要尝试一下才能找到问题。如果你发布一个完整的示例项目(在 github 上,或者一个存档文件或其他东西),以便我可以确定我的设置与你的匹配,我今晚会看看。
  • save 在父实体和子集合中运行良好,但只有更新会产生问题。如果你看到,错误是说它把student_id当作5,它不在数据库中,只有4的student_id在数据库中。
【解决方案2】:

“student_id”未与您的任何主键关联。如果学生和地址表中都存在“student_id”,则将学生映射文件中的这一行从“id”更改为“student_id”:

<id name="id" type="int" column="student_id">

【讨论】:

    【解决方案3】:

    使用数据库表查看器/浏览器仔细检查您的数据库表。 您似乎尝试插入数据库中已存在的 ID (5)

    【讨论】:

    • 不,它没有退出......我已经检查过......当我从其父实体更新任何子实体时发生了什么,然后它的父实体正在获取下一个增量 id
    猜你喜欢
    • 1970-01-01
    • 2020-09-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-23
    • 1970-01-01
    • 2019-03-28
    • 2016-03-08
    相关资源
    最近更新 更多