首页 > 解决方案 > 使用休眠更新记录的正确方法是什么,更改不会反映在数据库中?

问题描述

我有以下映射:

<hibernate-mapping>
<class name="com.jurnil.db.hibernate.Order" table="order_table">
    <id name="id" type="long" column="id">
        <generator class="identity"/>
    </id>
    <property name="shippingTotal">
        <column name="shipping_total" not-null="false"/>
    </property>
    <one-to-one name="shippingInfo" class="com.jurnil.db.hibernate.OrderShipping" cascade="all">
  </one-to-one> </class>
</hibernate-mapping>

我正在尝试从数据库中检索现有的“订单”,按顺序修改一些值并将它们更新回数据库。

以下是我拥有的 DAO 方法:

public boolean updateOrder(Order o) {
    Session s = HibernateUtil.getSessionFactory().getCurrentSession();
    Transaction tx = getTransaction(s);
    o.setUpdated(new Date());
    s.saveOrUpdate(o);
    tryCommit(tx);
    return true;

我打电话给orderDAO.updateOrder(order);

更改未反映在数据库中,并且在休眠日志中我可以看到Duplicate entry '332' for key 'PRIMARY'

当我尝试将会话重写updateOrder

Session s = HibernateUtil.getSessionFactory().openSession(); 

s.saveOrUpdate(o);给我以下错误,Duplicate entry '332' for key 'PRIMARY'

在尝试了@Guillaume 的建议之后

改变DAO方法:

public boolean updateOrder(BigDecimal cartTotal, OrderShipping shippingInformation, BigDecimal taxes,
            BigDecimal orderTotal, BigDecimal shippingTotal, Long id) {
        Session s = HibernateUtil.getSessionFactory().getCurrentSession();
        Transaction tx = getTransaction(s);
        Order order = (Order) s.load(Order.class, id);
        order.setCartTotal(cartTotal);
        order.setShippingInfo(shippingInformation);
        order.setTaxPaid(taxes);
        order.setTotalPaid(orderTotal);
        order.setShippingTotal(shippingTotal);
        order.getShippingInfo().setOrder(order);
        order.setUpdated(new Date());
        tryCommit(tx);
        return true;
    }

数据库中的数据仍未更新,在 SQL 日志中我可以看到事务正在回滚,为什么会发生这种情况?

下面是 SQL 日志

[2020-09-17 17:45:44,125] DEBUG org.hibernate.loader.entity.plan.AbstractLoadPlanBasedEntityLoader - Done entity load : com.jurnil.db.hibernate.Order#335
[2020-09-17 17:45:44,126] DEBUG org.hibernate.engine.transaction.spi.AbstractTransactionImpl - committing
[2020-09-17 17:45:44,126] DEBUG org.hibernate.event.internal.AbstractFlushingEventListener - Processing flush-time cascades
[2020-09-17 17:45:44,135] DEBUG org.hibernate.event.internal.AbstractSaveEventListener - Generated identifier: 335, using strategy: org.hibernate.id.ForeignGenerator
org.hibernate.NonUniqueObjectException: A different object with the same identifier value was already associated with the session : [com.jurnil.db.hibernate.OrderShipping#335]
[2020-09-17 17:45:44,136] DEBUG org.hibernate.engine.transaction.spi.AbstractTransactionImpl - rolling back

标签: javamysqlhibernatejpahibernate-mapping

解决方案


您的Order对象需要与您用于事务的会话相关联。例如,如果您想使用 id #322 更新订单:

Session s = HibernateUtil.getSessionFactory().getCurrentSession();
Transaction tx = getTransaction(s);
Order o = s.load(Order.class, 322);
o.setUpdated(new Date());
tryCommit(tx);

注意saveOrUpdate被删除:当事务提交时,Hibernate 会看到 Order 被修改并更新数据库。


推荐阅读