Java Hibernate-批处理更新从更新返回意外的行数:0实际行数:0预期:1

Java Hibernate-批处理更新从更新返回意外的行数:0实际行数:0预期:1,java,hibernate,Java,Hibernate,我得到以下休眠错误。我能够确定导致问题的功能。不幸的是,函数中有几个DB调用。我找不到导致问题的行,因为hibernate在事务结束时刷新会话。下面提到的hibernate错误看起来像一般错误。它甚至没有提到是哪个Bean导致了这个问题。有人熟悉这个休眠错误吗 org.hibernate.StaleStateException: Batch update returned unexpected row count from update: 0 actual row count: 0 expect

我得到以下休眠错误。我能够确定导致问题的功能。不幸的是,函数中有几个DB调用。我找不到导致问题的行,因为hibernate在事务结束时刷新会话。下面提到的hibernate错误看起来像一般错误。它甚至没有提到是哪个Bean导致了这个问题。有人熟悉这个休眠错误吗

org.hibernate.StaleStateException: Batch update returned unexpected row count from update: 0 actual row count: 0 expected: 1
        at org.hibernate.jdbc.BatchingBatcher.checkRowCount(BatchingBatcher.java:93)
        at org.hibernate.jdbc.BatchingBatcher.checkRowCounts(BatchingBatcher.java:79)
        at org.hibernate.jdbc.BatchingBatcher.doExecuteBatch(BatchingBatcher.java:58)
        at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:195)
        at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:235)
        at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:142)
        at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:297)
        at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:27)
        at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:985)
        at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:333)
        at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:106)
        at org.springframework.orm.hibernate3.HibernateTransactionManager.doCommit(HibernateTransactionManager.java:584)
        at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransacti
onManager.java:500)
        at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManag
er.java:473)
        at org.springframework.transaction.interceptor.TransactionAspectSupport.doCommitTransactionAfterReturning(Transaction
AspectSupport.java:267)
        at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:106)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:170)
        at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:176)

如果没有事务的代码和映射,调查问题几乎是不可能的

但是,要更好地了解问题的原因,请尝试以下操作:

<hibernate-mapping>
    <class name="path.to.class.Principal" table="principal_table" ...>
    ...
    <set name="middleObjects" table="middle_table" inverse="true" fetch="select">
        <key>
            <column name="PRINCIPAL_ID" not-null="true" />
        </key>
        <one-to-many class="path.to.class.Middel" />
    </set>
    ...
  • 在hibernate配置中,将hibernate.show_sql设置为true。这将向您显示执行的SQL以及导致问题的SQL
  • 将Spring和Hibernate的日志级别设置为DEBUG,这同样会让您更好地了解是哪一行导致了问题
  • 创建一个单元测试,它可以复制问题,而无需在Spring中配置事务管理器。这将使您更好地了解这一行有问题的代码

希望能有所帮助。

我在删除一条完全不存在的Id记录时遇到了相同的异常。因此,请检查您正在更新/删除的记录是否确实存在于DB中。我刚刚遇到这个问题,并发现我正在删除一个记录,然后在Hibernate事务中尝试更新它

如前所述,当对象的子对象被删除时,会发生这种情况。(可能是因为需要对整个父对象进行更新,有时我们更喜欢删除子对象并在父对象上重新插入它们(新的、旧的都不重要),以及父对象可能对其任何其他普通字段进行的任何其他更新) 因此…为了使这项工作正常,请通过调用
childrenList.clear()
(不要循环遍历子项,并使用一些
childDAO.delete(childrenList.get(i.delete())和设置来删除子项(在事务中)

@OneToMany(cascade=CascadeType.XXX,orphaneremovation=true)
位于父对象的一侧。然后更新父亲(fatherDAO.update(父亲))。(对每个父对象重复)结果是,子对象与父对象的链接被剥离,然后它们被框架作为孤立对象删除。

当您尝试删除同一对象,然后再次更新同一对象时,会发生这种情况。请在删除后使用此选项


session.clear()

当触发器执行影响行计数的附加DML(数据修改)查询时,可能会发生这种情况。我的解决方案是在触发器顶部添加以下内容:

SET NOCOUNT ON;

有一次,当我给一些对象分配特定的ID(测试)时,这种情况发生在我身上,然后我试图将它们保存在数据库中。问题是在数据库中有一个特定的策略用于设置对象的ID。如果您有Hibernate级别的策略,请不要分配ID。

我遇到了相同的问题,我验证了这可能是由于自动递增主键造成的。要解决此问题,请不要在数据集中插入自动增量值。插入没有主键的数据。

我遇到了这个问题,我们有一个多关系

在master的hibernate hbm映射文件中,对于具有set-type排列的对象,添加了
cascade=“save-update”
,效果良好

如果不这样做,默认情况下hibernate会尝试更新不存在的记录,并通过这样做,它会插入记录。

解决方案: 在id属性的Hibernate映射文件中,如果使用任何生成器类,则不应使用setter方法显式设置该属性的值

如果显式设置Id属性的值,则会导致上述错误。选中此选项可避免此错误。 或 当您在映射文件中提到字段生成器=“native”或“incremental”并且在数据库中映射的表没有自动递增时,会显示错误
解决方案:转到数据库并更新表以设置自动增量

当我在注释为
@Transactional
的方法中手动开始和提交事务时,遇到了这个问题。我通过检测活动事务是否已经存在,修复了这个问题

//Detect underlying transaction
if (session.getTransaction() != null && session.getTransaction().isActive()) {
    myTransaction = session.getTransaction();
    preExistingTransaction = true;
} else {
    myTransaction = session.beginTransaction();
}
然后我允许Spring处理提交事务

private void finishTransaction() {
    if (!preExistingTransaction) {
        try {
            tx.commit();
        } catch (HibernateException he) {
            if (tx != null) {
                tx.rollback();
            }
            log.error(he);
        } finally {
            if (newSessionOpened) {
                SessionFactoryUtils.closeSession(session);
                newSessionOpened = false;
                maxResults = 0;
            }
        }
    }
}

这也发生在我身上,因为我的id和视图一样长,并且我从视图接收到值0,当我试图保存到数据库中时,我得到了这个错误,然后我通过将id设置为null来修复它。

当您将JSF托管Bean声明为

@RequestScoped;
你什么时候应该申报为

@SessionScoped;
问候

我也面临同样的问题。 代码在测试环境中工作。但它在登台环境中不起作用

org.hibernate.jdbc.BatchedTooManyRowsAffectedException: Batch update returned unexpected row count from update [0]; actual row count: 3; expected: 1
问题是,在测试DB表时,表的每个主键都有一个条目。但在暂存数据库中,同一主键有多个条目。(问题是在暂存数据库中,表没有任何主键约束,并且存在多个条目。)

所以每次更新操作都会失败。它尝试更新单个记录,并期望更新计数为1。但由于同一主键在表中有3条记录,因此结果更新计数为3条。因为预期更新计数和实际结果更新计数不匹配,所以它抛出异常并回滚

之后,我删除了所有具有重复主键的记录,并添加了主键约束。它工作得很好

Hibernate - Batch update returned unexpected row count from update: 0 actual row count: 0 expected: 1
实际行数:0//表示未找到要更新的记录
更新:0//表示未找到任何记录,因此未进行任何更新
预期:1//表示预期至少有一条记录,其键位于db表中

这里的问题是,查询试图更新某个键的记录,但hibernate没有
session.beginTransaction();

Principal principal = new Principal();
principal.setSomething("1");
principal.setSomethingElse("2");


Middle middleObject = new Middle();
middleObject.setSomething("1");

middleObject.setPrincipal(principal);
principal.getMiddleObjects().add(middleObject);

session.saveOrUpdate(principal);
session.saveOrUpdate(middleObject); // NOTICE: you will need to save it manually

session.getTransaction().commit();
SessionFactory sf=new Configuration().configure().buildSessionFactory();
Session session=sf.openSession();

UserDetails user=new UserDetails();

session.beginTransaction();
user.setUserName("update user agian");
user.setUserId(12);
session.saveOrUpdate(user);
session.getTransaction().commit();
System.out.println("user::"+user.getUserName());

sf.close();
Detail detail = getDetail(Long.valueOf(1396451));
session.delete(detail);
session.flush();
session.delete(detail);
session.flush();
     try
    {
        if(!session.isOpen())
        {
            session=EmployeyDao.getSessionFactory().openSession();
        }
            tx=session.beginTransaction();

        session.evict(e);
        session.saveOrUpdate(e);
        tx.commit();;
        EmployeyDao.shutDown(session);
    }
    catch(HibernateException exc)
    {
        exc.printStackTrace();
        tx.rollback();
    }
if ( expectedRowCount > rowCount ) {
    throw new StaleStateException(
            "Batch update returned unexpected row count from update ["
                    + batchPosition + "]; actual row count: " + rowCount
                    + "; expected: " + expectedRowCount + "; statement executed: "
                    + statement
    );
}
@Entity(name = "Post")
@Table(name = "post")
public class Post {

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE)
    private Long id;

    private String title;

    @Version
    private short version;

    public Long getId() {
        return id;
    }

    public Post setId(Long id) {
        this.id = id;
        return this;
    }

    public String getTitle() {
        return title;
    }

    public Post setTitle(String title) {
        this.title = title;
        return this;
    }

    public short getVersion() {
        return version;
    }
}
properties.put("hibernate.jdbc.batch_size", "5");
properties.put("hibernate.order_inserts", "true");
properties.put("hibernate.order_updates", "true");
doInJPA(entityManager -> {
    for (int i = 1; i <= 3; i++) {
        entityManager.persist(
            new Post()
                .setTitle(String.format("Post no. %d", i))
        );
    }
});
SELECT nextval ('hibernate_sequence')
SELECT nextval ('hibernate_sequence')
SELECT nextval ('hibernate_sequence')

Query: [
    INSERT INTO post (title, version, id) 
    VALUES (?, ?, ?)
], 
Params:[
    (Post no. 1, 0, 1), 
    (Post no. 2, 0, 2), 
    (Post no. 3, 0, 3)
]
doInJPA(entityManager -> {
    List<Post> posts = entityManager.createQuery("""
        select p 
        from Post p
        """, Post.class)
    .getResultList();

    posts.forEach(
        post -> post.setTitle(
            post.getTitle() + " - 2nd edition"
        )
    );

    executeSync(
        () -> doInJPA(_entityManager -> {
            Post post = _entityManager.createQuery("""
                select p 
                from Post p
                order by p.id
                """, Post.class)
            .setMaxResults(1)
            .getSingleResult();

            post.setTitle(post.getTitle() + " - corrected");
        })
    );
});
Query:[
    UPDATE 
        post 
    SET 
        title = ?, 
        version = ? 
    WHERE 
        id = ? AND 
        version = ?
], 
Params:[
    ('Post no. 1 - corrected', 1, 1, 0)
]
Query:[
    UPDATE 
        post 
    SET 
        title = ?, 
        version = ? 
    WHERE 
        id = ? AND 
        version = ?
], 
Params:[
    ('Post no. 1 - 2nd edition', 1, 1, 0), 
    ('Post no. 2 - 2nd edition', 1, 2, 0), 
    ('Post no. 3 - 2nd edition', 1, 3, 0)
]

o.h.e.j.b.i.AbstractBatchImpl - HHH000010: On release of batch it still contained JDBC statements

o.h.e.j.b.i.BatchingBatch - HHH000315: Exception executing batch [
    org.hibernate.StaleStateException: 
    Batch update returned unexpected row count from update [0]; 
    actual row count: 0; 
    expected: 1; 
    statement executed: 
        PgPreparedStatement [
            update post set title='Post no. 3 - 2nd edition', version=1 where id=3 and version=0
        ]
], 
SQL: update post set title=?, version=? where id=? and version=?