使用HQL查询实现Hibernate批量更新

6

我正在使用Hibernate作为我的ORM层。 我试图在一个事务中运行一批HQL查询(我不能使用session.update)。 问题是,即使transaction.commit()在循环的末尾,更新查询也会逐个运行。 有没有办法在一个事务中运行多个HQL查询?

public void updateItems() {
    t = session.beginTransaction();
    for (int i = 0; i < itemList.size(); i++) {
        Query q = createUpdateQuery(session, itemList.get(i));      
        q.executeUpdate(); //updating one by one, and not waiting for transaction commit
    }
    t.commit();
}



Query createUpdateQuery(Session session, Item item) {
    Query q = session.createQuery(
                "Update Item i set i.notes=:notes, i.time=:time, i.counter=:counter, i.status=:status Where i.id=:id and i.time=:time");

    q.setParameter("time", item.getTime());
    q.setParameter("status", item.getStatus());
    q.setParameter("notes", item.getNotes());
    q.setParameter("id", item.getId());
    return q;
}

感谢任何帮助。

我没有看到你的代码有什么明显的问题。更新将逐个在数据库上进行,但在调用commit之前不会提交。您应该能够在调用commit之前随时回滚事务。这是非常标准的。您只是担心往返数据库的次数吗? - markwatsonatx
仅有一个事务并不意味着以大批量发送多个更新。而且,在您的方法中有太多不正确的地方(我希望这不是您在生产代码中要做的)。 - Adrian Shum
感谢您的回复。我需要从session.update(item)更改为这种方法,但性能有所下降。 - Lasti
在我看来,您正在以一种不适合的方式使用Hibernate。 您应该提前开启事务(可能在整个业务服务周围),获取实体,直接更新实体,并在提交事务时让Hibernate负责更新。通过这样做,使用适当的批量大小设置,Hibernate将知道同一类型的多个实体已更新,并利用JDBC批量操作更新多个记录,在此过程中减少了往返次数。 - Adrian Shum
1个回答

2
您正在使用数据库事务来注册所有语句,但我认为您想使用批量更新。只需添加以下配置属性:
<property name="hibernate.jdbc.batch_size" value="10"/>

即便如此,我认为你应该使用Hibernate来管理插入/更新/删除语句,因为你只需要关注实体状态的转换。脏数据检查机制可以自动检测已经被修改的实体,并且Hibernate可以为你生成更新语句,这样更加方便。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接