【问题标题】:Hibernate: Session.update() not working休眠:Session.update() 不工作
【发布时间】:2015-12-17 15:44:18
【问题描述】:

我正在开发一个 Hibernate+Spring+MYSQL 项目。我在尝试更新子表(外键表)时遇到问题 我可以插入和删除条目,但无法更新。我尝试了很多方法,但没有任何效果。

PurchaseOrder 上的 CRUD 操作,即父表工作正常。

我已经从 hibernate revenge 文件 xml 创建了实体。

Table Relation:

PurchaseOrderPurchaseOrderDetail 具有一对多关系。

我的实体是,

TpurchaseOrder.java

@Entity
@Table(name = "tpurchase_order", catalog = "peonydb")
public class TpurchaseOrder implements java.io.Serializable {

private long purchaseId;
private long VId;
private float purchaseAmount;
private Date paymentDueDate;
private float vat;
private boolean purchaseApproval;
private Set<TpurchaseOrderDetail> tpurchaseOrderDetails = new HashSet<TpurchaseOrderDetail>(0);

public TpurchaseOrder() {
}

public TpurchaseOrder(long purchaseId, long VId, float purchaseAmount, Date paymentDueDate, float vat,
        boolean purchaseApproval) {
    this.purchaseId = purchaseId;
    this.VId = VId;
    this.purchaseAmount = purchaseAmount;
    this.paymentDueDate = paymentDueDate;
    this.vat = vat;
    this.purchaseApproval = purchaseApproval;
}

public TpurchaseOrder(long purchaseId, long VId, float purchaseAmount, Date paymentDueDate, float vat,
        boolean purchaseApproval, Set<TpurchaseOrderDetail> tpurchaseOrderDetails) {
    this.purchaseId = purchaseId;
    this.VId = VId;
    this.purchaseAmount = purchaseAmount;
    this.paymentDueDate = paymentDueDate;
    this.vat = vat;
    this.purchaseApproval = purchaseApproval;
    this.tpurchaseOrderDetails = tpurchaseOrderDetails;
}

@Id

@Column(name = "PURCHASE_ID", unique = true, nullable = false)
public long getPurchaseId() {
    return this.purchaseId;
}

public void setPurchaseId(long purchaseId) {
    this.purchaseId = purchaseId;
}

@Column(name = "V_ID", nullable = false)
public long getVId() {
    return this.VId;
}

public void setVId(long VId) {
    this.VId = VId;
}

@Column(name = "PURCHASE_AMOUNT", nullable = false, precision = 12, scale = 0)
public float getPurchaseAmount() {
    return this.purchaseAmount;
}

public void setPurchaseAmount(float purchaseAmount) {
    this.purchaseAmount = purchaseAmount;
}

@Temporal(TemporalType.DATE)
@Column(name = "PAYMENT_DUE_DATE", nullable = false, length = 0)
public Date getPaymentDueDate() {
    return this.paymentDueDate;
}

public void setPaymentDueDate(Date paymentDueDate) {
    this.paymentDueDate = paymentDueDate;
}

@Column(name = "VAT", nullable = false, precision = 12, scale = 0)
public float getVat() {
    return this.vat;
}

public void setVat(float vat) {
    this.vat = vat;
}

@Column(name = "PURCHASE_APPROVAL", nullable = false)
public boolean isPurchaseApproval() {
    return this.purchaseApproval;
}

public void setPurchaseApproval(boolean purchaseApproval) {
    this.purchaseApproval = purchaseApproval;
}

@OneToMany(fetch = FetchType.LAZY, mappedBy = "tpurchaseOrder")
public Set<TpurchaseOrderDetail> getTpurchaseOrderDetails() {
    return this.tpurchaseOrderDetails;
}

public void setTpurchaseOrderDetails(Set<TpurchaseOrderDetail> tpurchaseOrderDetails) {
    this.tpurchaseOrderDetails = tpurchaseOrderDetails;
}

}

TpurchaseOrderDetail.java

@Entity
@Table(name = "tpurchase_order_detail", catalog = "peonydb",     uniqueConstraints = @UniqueConstraint(columnNames = {
    "PURCHASE_ID", "PROD_ID" }) )
public class TpurchaseOrderDetail implements java.io.Serializable {

private TpurchaseOrderDetailId id;
private TpurchaseOrder tpurchaseOrder;

public TpurchaseOrderDetail() {
}

public TpurchaseOrderDetail(TpurchaseOrderDetailId id, TpurchaseOrder tpurchaseOrder) {
    this.id = id;
    this.tpurchaseOrder = tpurchaseOrder;
}

@EmbeddedId

@AttributeOverrides({
        @AttributeOverride(name = "purchaseId", column = @Column(name = "PURCHASE_ID", nullable = false) ),
        @AttributeOverride(name = "prodId", column = @Column(name = "PROD_ID", nullable = false) ),
        @AttributeOverride(name = "prodQuantity", column = @Column(name = "PROD_QUANTITY", nullable = false) ),
        @AttributeOverride(name = "prodUnitRate", column = @Column(name = "PROD_UNIT_RATE", nullable = false, precision = 12, scale = 0) ) })
public TpurchaseOrderDetailId getId() {
    return this.id;
}

public void setId(TpurchaseOrderDetailId id) {
    this.id = id;
}

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "PURCHASE_ID", nullable = false, insertable = false, updatable = false)
public TpurchaseOrder getTpurchaseOrder() {
    return this.tpurchaseOrder;
}

public void setTpurchaseOrder(TpurchaseOrder tpurchaseOrder) {
    this.tpurchaseOrder = tpurchaseOrder;
}

}

TpurchaseOrderDetailId.java

@Embeddable
public class TpurchaseOrderDetailId implements java.io.Serializable {

private long purchaseId;
private long prodId;
private long prodQuantity;
private float prodUnitRate;

public TpurchaseOrderDetailId() {
}

public TpurchaseOrderDetailId(long purchaseId, long prodId, long prodQuantity, float prodUnitRate) {
    this.purchaseId = purchaseId;
    this.prodId = prodId;
    this.prodQuantity = prodQuantity;
    this.prodUnitRate = prodUnitRate;
}

@Column(name = "PURCHASE_ID", nullable = false)
public long getPurchaseId() {
    return this.purchaseId;
}

public void setPurchaseId(long purchaseId) {
    this.purchaseId = purchaseId;
}

@Column(name = "PROD_ID", nullable = false)
public long getProdId() {
    return this.prodId;
}

public void setProdId(long prodId) {
    this.prodId = prodId;
}

@Column(name = "PROD_QUANTITY", nullable = false)
public long getProdQuantity() {
    return this.prodQuantity;
}

public void setProdQuantity(long prodQuantity) {
    this.prodQuantity = prodQuantity;
}

@Column(name = "PROD_UNIT_RATE", nullable = false, precision = 12, scale = 0)
public float getProdUnitRate() {
    return this.prodUnitRate;
}

public void setProdUnitRate(float prodUnitRate) {
    this.prodUnitRate = prodUnitRate;
}

public boolean equals(Object other) {
    if ((this == other))
        return true;
    if ((other == null))
        return false;
    if (!(other instanceof TpurchaseOrderDetailId))
        return false;
    TpurchaseOrderDetailId castOther = (TpurchaseOrderDetailId) other;

    return (this.getPurchaseId() == castOther.getPurchaseId()) && (this.getProdId() == castOther.getProdId())
            && (this.getProdQuantity() == castOther.getProdQuantity())
            && (this.getProdUnitRate() == castOther.getProdUnitRate());
}

public int hashCode() {
    int result = 17;

    result = 37 * result + (int) this.getPurchaseId();
    result = 37 * result + (int) this.getProdId();
    result = 37 * result + (int) this.getProdQuantity();
    result = 37 * result + (int) this.getProdUnitRate();
    return result;
}

}

更新代码方法:

@Transactional
@Override
public String updatePO(PurchaseOrderPojo purchaseOrderPojo,
        ArrayList<PurchaseOrderDetailIdPojo> updatedPurchasedProductsList, String purchaseId) {
    final Transaction transaction;
    try {
        if (this.session != null && !this.session.isConnected()) {
            this.session = this.sessionFactory.openSession();
        } else {
            this.session = this.sessionFactory.getCurrentSession();
        }
        transaction = session.beginTransaction();

        TpurchaseOrder tpurchaseOrder = (TpurchaseOrder) session.get(TpurchaseOrder.class,
                Long.parseLong(purchaseId));

        List<TpurchaseOrderDetail> tpurchaseOrderDetailListFromDB = null;
        if (purchaseOrderPojo != null) {
            tpurchaseOrder.setVId(purchaseOrderPojo.getVId());
            tpurchaseOrder.setVat(purchaseOrderPojo.getVat());
            // to be set later on once the PO is approved
            tpurchaseOrder.setPurchaseApproval(false);
            tpurchaseOrder.setPaymentDueDate(DateUtils.StringtoUtilDate(purchaseOrderPojo.getPaymentDueDate()));
            tpurchaseOrder.setPurchaseAmount(getPurchaseAmount(purchaseOrderPojo, updatedPurchasedProductsList));
            session.update(tpurchaseOrder); // THIS WORKS FINE I CAN SEE UPDATE QUERY ON CONSOLE FOR THIS PARENT TABLE

            Criteria criteria = session.createCriteria(TpurchaseOrderDetail.class);
            criteria.add(Restrictions.eq("id.purchaseId", Long.parseLong(purchaseId)));
            tpurchaseOrderDetailListFromDB = criteria.list();

            for (PurchaseOrderDetailIdPojo purchaseOrderDetailIdUpdatedObj : updatedPurchasedProductsList) {
                isObjectPresent = false;
                for (TpurchaseOrderDetail tpurchaseOrderDetailObjFromDB : tpurchaseOrderDetailListFromDB) {
                    // if the purchase product is already present in the DB
                    // then update it

                    if (tpurchaseOrderDetailObjFromDB.getId().getProdId() == purchaseOrderDetailIdUpdatedObj
                            .getProdId()) {
                        TpurchaseOrderDetailId tpurchaseOrderDetailId = tpurchaseOrderDetailObjFromDB.getId();
                        tpurchaseOrderDetailId.setProdQuantity(purchaseOrderDetailIdUpdatedObj.getProdQuantity());                          
                        tpurchaseOrderDetailId.setProdUnitRate(purchaseOrderDetailIdUpdatedObj.getProdUnitRate());
                        tpurchaseOrderDetailObjFromDB.setId(tpurchaseOrderDetailId);

                        session.update(tpurchaseOrderDetailObjFromDB); // THIS IS NOT WORKING, I EVEN TRIED USING saveOrUpdate METHOD
                        session.flush();                            
                    }                       
                }
            }
        }
        transaction.commit();
        return StringConstants.SUCCESS_STR;
    } catch (Exception exception) {
        // rollback procedure to be implemented
        exception.printStackTrace();
        return exception.getMessage();
    }
}

【问题讨论】:

  • 很高兴您提供了代码,但其中有很多!您能否简化示例,同时仍然重现问题?这样做时,您也可能自己找到答案。
  • 另外,您能否解释一下您所说的“不工作”是什么意思——您是否遇到错误?更新代码根本不运行吗?还是它运行但实际上并没有进行更新?
  • @devlin :感谢您的评论,不工作是指没有更新查询会在子表(即 PurchaseOrderDetail 表)上触发。记录不会更新。在代码部分中,我提供的只是实体。 :) 如果你愿意,我会尽量减少。

标签: java mysql hibernate


【解决方案1】:

更新失败的原因是您试图更改记录的主键,这在关系数据库中是不允许的。

我会建议以下内容(为简洁起见,删除了注释/getters/setters)。

TpurchaseOrderDetailId.java

public class TpurchaseOrderDetailId {
  private long purchaseId;
  private long prodId;
}

TpurchaseOrderDetail.java

public class TpurchaseOrderDetail {
  private TpurchaseOrderDetailId id;
  private TpurchaseOrder tpurchaseOrder;
  private long prodQuantity;
  private float prodUnitRate;
}

这将允许 prodQuantityprodUnitRateTpurchaseOrderDetail 行的整个生命周期内更改,而您的原始代码不会。

【讨论】:

  • 感谢您的回答。你能告诉我我在哪里改变PK吗?而且在更新记录时我没有收到任何错误。问题是更新命令本身不会在 session.update(tpurchaseOrderDetailObjFromDB); 行上触发;
猜你喜欢
  • 1970-01-01
  • 2017-10-19
  • 2017-02-16
  • 2012-04-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多