Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/342.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 休眠:flush()和commit()_Java_Hibernate_Orm - Fatal编程技术网

Java 休眠:flush()和commit()

Java 休眠:flush()和commit(),java,hibernate,orm,Java,Hibernate,Orm,单独调用org.hibernate.Session.flush()是否是一种好的做法 如org.hibernate.Sessiondocs中所述 必须在工作单元结束时调用,然后提交事务并关闭会话(取决于刷新模式,transaction.commit()调用此方法) 如果org.hibernate.Transaction.commit()已经可以调用flush() Session session = sessionFactory.openSession(); Transaction tx = se

单独调用
org.hibernate.Session.flush()
是否是一种好的做法

org.hibernate.Session
docs中所述

必须在工作单元结束时调用,然后提交事务并关闭会话(取决于刷新模式,transaction.commit()调用此方法)


如果
org.hibernate.Transaction.commit()
已经可以调用
flush()

Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();

for (int i = 0; i < 100000; i++) {
    Customer customer = new Customer(...);
    session.save(customer);
    if (i % 20 == 0) { // 20, same as the JDBC batch size
        // flush a batch of inserts and release memory:
        session.flush();
        session.clear();
    }
}

tx.commit();
session.close();
Session Session=sessionFactory.openSession();
事务tx=会话.beginTransaction();
对于(int i=0;i<100000;i++){
客户=新客户(…);
session.save(客户);
如果(i%20==0){//20,则与JDBC批处理大小相同
//刷新一批插入并释放内存:
session.flush();
session.clear();
}
}
tx.commit();
session.close();
如果不调用flush方法,一级缓存将抛出OutOfMemoryException


默认情况下,刷新模式是自动的,这意味着:“有时会在执行查询之前刷新会话,以确保查询不会返回过时状态”,但大多数情况下,在提交更改时会刷新会话。当您使用FlushMode=Manual或希望进行某种优化时,手动调用flush方法非常有用。但是我从来没有这样做过,所以我不能给你实际的建议。

显式刷新的一个常见情况是,当你创建一个新的持久实体,你希望它有一个人工主键生成并分配给它,以便你以后可以在同一事务中使用它。在这种情况下,调用flush将导致您的实体获得一个id

另一种情况是,如果一级缓存中有很多内容,并且您希望定期将其清除(以减少缓存使用的内存量),但仍然希望将整个内容一起提交。这就是所涉及的情况。

flush()刷新是将底层持久存储与内存中的持久状态同步的过程。它将在正在运行的事务中更新或插入到您的表中,但可能不会提交这些更改

您需要在批处理中刷新,否则可能会 OutOfMemoryException.

Commit()提交将使数据库提交。当您有一个持久化对象并且更改了该对象上的值时,它会变脏,hibernate需要将这些更改刷新到持久化层。因此,您应该提交,但它也会结束工作单元(
transaction.commit()
)。

flush()
将数据库与内存中对象的当前状态同步,但不会提交事务。因此,如果调用
flush()
后出现异常,则事务将回滚。 您可以使用
flush()
将数据库与小数据块同步,而不是使用
commit()
立即提交大数据,并面临从内存异常中获取
的风险

commit()
将使存储在数据库中的数据永久化。一旦
commit()
成功,您就无法回滚事务。

session.flush()是一种同步方法,用于按顺序将数据插入数据库。如果使用此方法,数据不会存储在数据库中,但会存储在缓存中,如果中间出现任何异常,我们可以处理它。
但commit()会将数据存储在数据库中,如果我们存储更多的数据,可能会出现内存不足异常,就像在保存点主题的JDBC程序中一样,除非必要,否则通常不建议显式调用flush。Hibernate通常在事务结束时自动调用Flush,我们应该让它完成它的工作。现在,在某些情况下,您可能需要显式调用flush,其中第二个任务取决于第一个持久性任务的结果,这两个任务都在同一事务中

例如,您可能需要持久化一个新实体,然后使用该实体的Id在同一事务中执行其他任务,在这种情况下,需要首先显式刷新该实体

@Transactional
void someServiceMethod(Entity entity){
    em.persist(entity); 
    em.flush() //need to explicitly flush in order to use id in next statement
    doSomeThingElse(entity.getId());    
}

还请注意,显式刷新不会导致数据库提交,数据库提交仅在事务结束时完成,因此,如果调用刷新后发生任何运行时错误,更改仍将回滚

你能参考一下这篇文章吗?这个答案给出了一个具体的例子,在这个例子中,显式地调用flush是一个好主意,但我不认为它解决了是否应该始终这样做的一般问题。嗨@KorayTugay。我很长一段时间都没有使用新版本hibernate的经验。但是以前如果没有clean,您可能会收到一些意想不到的结果。因此,我建议尝试不同的方法,甚至检查最新的文档。如果您仔细查看,您可以使用
@Transactional
注释插入
sessionFactory
。从那时起,你不需要你的代码到处都是事务性的(但在某些情况下需要)。我在代码中遇到了一个有趣的情况,我必须合并一个已经从客户端应用程序生成了id的实体,然后刷新同一个实体以获得数据库生成的字段,例如创建和修改日期。如果不调用session.flush(),它会抛出一个object not found异常,因为合并调用有时会被忽略,直到事务结束。当我在合并调用之后添加flush时,它会强制hibernate执行实际查询,然后刷新对象,因为它现在存在于数据库中!如果您想访问生成的PK imme