如果我们在hibernate中开始事务,然后做一些事务但不提交它会发生什么? 它会拯救它还是会立即回滚?
由于 阿赫亚
答案 0 :(得分:4)
查看以下代码,该代码使用事务边界访问数据库,而不使用commit:
Session session = sessionFactory.openSession();
session.beginTransaction();
session.get(Item.class, 123l);
session.close();
默认情况下,在具有JDBC配置的Java SE环境中,如果您执行此代码段会发生这种情况:
SELECT在此JDBC事务中执行。会议是 关闭,连接返回到池并释放 Hibernate - Hibernate在JDBC Connection上调用close()。
未提交的交易会怎样?
该问题的答案是,“它取决于!”在连接上调用close()时,JDBC规范没有提及有关挂起事务的任何信息。发生的情况取决于供应商如何实施规范。例如,使用Oracle JDBC驱动程序,对close()的调用将提交事务!当JDBC Connection对象关闭并且资源返回到池时,大多数其他JDBC供应商采用理智的路由并回滚任何挂起的事务。
显然,这对你执行的SELECT不会有问题,但请看这个变化:
Session session = getSessionFactory().openSession();
session.beginTransaction();
Long generatedId = session.save(item);
session.close();
此代码生成一个INSERT语句,在从未提交或回滚的事务中执行。在Oracle上,这段代码永久地插入数据;在其他数据库中,它可能不会。(这种情况稍微复杂一点:只有在标识符生成器需要它时才执行INSERT。例如,可以从没有INSERT的序列中获取标识符值。持久性然后将实体排队,直到刷新时间插入 - 这在此代码中永远不会发生。身份策略需要立即INSERT才能生成该值。)
答案 1 :(得分:0)
它依赖于hibernate-config和连接池配置。
当尝试关闭一个打开事务的会话时,默认情况下hibernate不会调用关闭连接代理(如果你想改变这个你需要定义--hibernate.ejb.discard_pc_on_close是真的)
public void close() {
if ( !open ) {
throw new IllegalStateException( "EntityManager is closed" );
}
if ( !discardOnClose && isTransactionInProgress() ) {
现在,假设您定义了discard_pc_on_close,而不是在这种情况下,hibernate将调用关闭连接代理(连接池包装连接),所以现在我们依赖于连接池如何实现它。 您可以在:NewPooledConnection中看到c3p0实现。 您将看到它依赖于此标志 - FORCE_IGNORE_UNRESOLVED_TXNS(默认为false),因此默认情况下它将重置事务。
static void resetTxnState( Connection pCon,
boolean forceIgnoreUnresolvedTransactions,
boolean autoCommitOnClose,
boolean txnKnownResolved ) throws SQLException
{
if ( !forceIgnoreUnresolvedTransactions && !pCon.getAutoCommit() )