如何在不同的会话中保存具有相同外键的休眠对象

时间:2018-07-04 10:56:30

标签: java hibernate hibernate-mapping

在不同的会话中使用相同的外键保存休眠对象时出现错误。 下面是休眠类:

OrderInfo.java

@Entity
@Table(name = "ORDER_INFO", uniqueConstraints = {
        @UniqueConstraint(columnNames = {"ORDER_ID", "CREATION_TIMESTAMP"})
})
public class OrderInfo implements Serializable {
        @Id
        @Column(name = "ORDER_PK")
        @GeneratedValue(strategy = GenerationType.AUTO)
        private Long OrderPK;

        @Column(name = "ORDER_ID", nullable = false)
        private String OrderId;
        @Column(name = "CREATION_TIMESTAMP", nullable = false)
        private String creationTimestamp;
        @Column(name = "USER", nullable = false)
        private String user;
    }

OrderLeg.java

@Entity
@Table(name = "ORDER_LEG")
@IdClass(OrderLegKey.class)
public class OrderLeg implements  Serializable {
    @Id
    private Integer legIndex;
    @Id
    @ManyToOne
    @JoinColumn(name = "ORDER_FK", referencedColumnName = "ORDER_PK")
    private OrderInfo OrderFK;
    @Column(name = "LEG_DESC")
    private String legDesc; 

    //Constructor
    public OrderLeg(Integer legIndex, OrderInfo OrderFK) {
        this.legIndex = legIndex;
        this.orderFK = OrderFK;
    }
}

OrderLegKey.java

public class OrderLegKey implements Serializable {

    private Integer legIndex;
    private Long OrderFK;

    public Integer getLegIndex() {
        return legIndex;
    }
    public void setLegIndex(Integer legIndex) {
        this.legIndex = legIndex;
    }
    public Long getOrderFK() {
        return OrderFK;
    }
    public void setOrderFK(Long OrderFK) {
        this.OrderFK = OrderFK;
    }
}

OrderInfo表包含有关可以包含多个orderLeg的订单的信息。OrderLeg表具有引用到OrderPK表的OrderInfo列的外键。要求是可以在不同的会话中将OrderLegs添加到OrderInfo。第一次在同一会话中成功保存成功,但是下次在不同会话中成功保存OrderLegs到已经保存的OrderInfo记录中。下面是保存对象的代码:

public static void main(String[] args) {
        //Below is SUCCESS
        Session session = HibernateUtils.getSession();
        OrderInfo OrderInfo = new OrderInfo();
        OrderInfo.setOrderId("o2");
        OrderInfo.setCreationTimestamp("t1");
        OrderInfo.setUser("dan");
        OrderLeg leg1 = new OrderLeg(1, OrderInfo);
        OrderLeg leg2 = new OrderLeg(2, OrderInfo);
        try {
            session.beginTransaction();
            session.save(OrderInfo);
            session.save(leg1);
            session.save(leg2);
            session.getTransaction().commit();
        } finally {
            session.close();
        }

        //Below gets FAILED
        session = HibernateUtils.getSession();
        OrderLeg leg3 = new OrderLeg(3, OrderInfo);
        OrderLeg leg4 = new OrderLeg(4, OrderInfo);
        try {
            session.beginTransaction();
            session.save(OrderInfo);
            session.save(leg3);
            session.save(leg4);
            session.getTransaction().commit();
        } finally {
            session.close();
        }
    }

在第二个会话中保存对象时,出现异常:

Exception in thread "main" org.hibernate.exception.ConstraintViolationException: could not execute statement
    at org.hibernate.exception.internal.SQLExceptionTypeDelegate.convert(SQLExceptionTypeDelegate.java:59)
.............................
.............................
Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Duplicate entry 'o3-t1' for key 'UKoq9eddrx65xhf1gudrs0csrw2'
............................

问题是,当我尝试在第二个会话中保存Orderleg时,休眠模式首先运行OrderInfo的插入查询,该查询已保存在数据库中,这就是为什么ConstrainVoilation异常发生的原因。

  1. 因此,我的问题是如何处理需要创建外键(如在OrderLeg表中)并用相同的外键保存具有不同会话(在不同运行时)的子记录的此类情况。
  2. 在保存OrderInfo对象时,可以避免对OrderLeg进行插入查询吗? (当我尝试保存Orderleg对象时,Hibernate首先对OrderInfo运行插入查询,然后对OrderLeg对象运行插入查询)
  3. 在保持表之间的外键约束的同时,休眠中是否还有其他方法可以处理这种情况?

欢迎提出任何建议。预先感谢。

0 个答案:

没有答案