【问题标题】:Batch update returned unexpected row count from update [0];批量更新从更新 [0] 返回了意外的行数;
【发布时间】:2017-12-09 13:21:42
【问题描述】:

我使用这个实体来记录到数据库中。

@Entity
@Table(name = "SYSTEM_USERS")
public class SystemUsersModel implements Serializable
{
    private static final long serialVersionUID = 8432414340180447723L;

    @Id
    @GeneratedValue
    private Integer id;

    @Column
    private String username;

    @Column
    private String email;

    @Column
    @Type(type = "date")
    @Temporal(TemporalType.DATE)
    private Date lastlogin;

    @Column
    private String password;

    @Column
    private String salt;

    @Column
    @Type(type = "date")
    @Temporal(TemporalType.DATE)
    private Date added;

删除查询:

SessionFactory factory = HibernateUtils.getSessionFactory();
        Session session = factory.getCurrentSession();

        try
        {
            session.getTransaction().begin();

            SystemUsersModel obj = new SystemUsersModel();
            obj.setId(userlist.getId());

            session.delete(obj);

            session.getTransaction().commit();

            blacklists.remove(selectedBlackListEntry);
            selectedBlackListEntry = null;
        }
        catch (Exception e)
        {
            e.printStackTrace();
            session.getTransaction().rollback();
        }

然后我运行代码我得到这个错误:

Caused by: org.hibernate.StaleStateException: Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1

在启动应用程序之前,我已经使用脚本插入了几行。 我该如何解决这个问题?

【问题讨论】:

  • Hibernate 在设置 id 时不太喜欢,你确定对象在指定 ID 的 db 中吗?尝试通过 id 查找对象,然后修改你需要的内容
  • 当你询问异常时,总是,总是发布异常的完整堆栈跟踪。也就是说,问题很可能是您正在删除一个不存在的行。
  • 这里是完整的堆栈跟踪pastebin.com/sFGMNGim
  • 我猜 Frederico Paparoni 是对的。 Hibernate 使用代理对象和设置 ID 不适用于排除。

标签: java hibernate


【解决方案1】:

当您使用休眠管理对象实例时,它们必须“附加”到会话。

如果您使用new 创建一个对象,您需要先将其附加到会话中,然后才能使用休眠对其进行管理。

当一个对象(带有生成的 id)有一个 id 值时,hibernate 期望该对象存在于他的会话中(因为 id 值只有在 hibernate 生成它或 hibernate 通过查询从数据库中获取它时才存在) ,否则会抛出 Stale Exception。

您必须在其上调用 saveOrUpdate 以让 hibernate 创建其 Id 并将实例附加到会话(以防它在数据库中不存在),或者使用 ID 调用 load 以进行休眠从数据库中获取实例(如果它存在于数据库中)。

在这种情况下,您知道 id,因此您必须查询 hibernate 以获取附加的实例。所以,试试这个吧:

SystemUsersModel obj = session.load(SystemUsersModel.class, userlist.getId());
session.delete(obj);

这里是休眠会话的实例方面的不同状态的解释:https://docs.jboss.org/hibernate/orm/3.3/reference/en/html/objectstate.html

编辑:感谢@vanoekel

或者更好,而不是load,您可以使用getReference,因为如果您只是想在之后删除它,那么它在资源方面会更便宜。

【讨论】:

  • 除了加载整个实体只是为了删除它,还可以创建引用,参见stackoverflow.com/a/40468433/3080094
  • @GhostCat 甚至没有注意到,所以不用担心 :) 感谢您的支持:D
  • @Peter Penzov 我想补充一点,其他 ORM 提供者的这种行为应该是相同的,因为它记录在 JPA 级别
【解决方案2】:

以下行可能发生异常

如果您的对象具有自动生成的主键并且您强制分配键可能会导致异常。

详细解释请访问此页面HERE

【讨论】:

  • 我敢说这极不可能。结果对象仅用于请求删除底层数据库记录。您描述的情况是您想要更新或插入记录。
猜你喜欢
  • 2016-07-17
  • 2014-03-04
  • 2011-04-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-11
相关资源
最近更新 更多