Java Hibernate save() 和事务回滚
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2605594/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Hibernate save() and transaction rollback
提问by Mark
In Hibernate when i save()
an object in a transaction, and then i rollback it, the saved object still remains in the DB. It's strange because this issue doesn't happen with the update()
or delete()
method, just with save()
.
Here is the code i'm using:
在 Hibernate 中,当我save()
在事务中创建一个对象,然后回滚它时,保存的对象仍保留在数据库中。这很奇怪,因为这个问题不会发生在update()
ordelete()
方法上,只是发生在save()
.
这是我正在使用的代码:
DbEntity dbEntity = getDbEntity();
HibernateUtil.beginTransaction();
Session session = HibernateUtil.getCurrentSession();
session.save(dbEntity);
HibernateUtil.rollbackTransaction();
And here is the HibernateUtilclass (just the involved functions, i guarantee the getSessionFactory()
method works well - there is an Interceptor handler, but it doesn't matter now):
这是HibernateUtil类(只是涉及的函数,我保证该getSessionFactory()
方法运行良好 - 有一个拦截器处理程序,但现在无关紧要):
private static final ThreadLocal<Session> threadSession = new ThreadLocal<Session>();
private static final ThreadLocal<Transaction> threadTransaction = new ThreadLocal<Transaction>();
/**
* Retrieves the current Session local to the thread.
* <p/>
* If no Session is open, opens a new Session for the running thread.
*
* @return Session
*/
public static Session getCurrentSession()
throws HibernateException {
Session s = (Session) threadSession.get();
try {
if (s == null) {
log.debug("Opening new Session for this thread.");
if (getInterceptor() != null) {
log.debug("Using interceptor: " + getInterceptor().getClass());
s = getSessionFactory().openSession(getInterceptor());
} else {
s = getSessionFactory().openSession();
}
threadSession.set(s);
}
} catch (HibernateException ex) {
throw new HibernateException(ex);
}
return s;
}
/**
* Start a new database transaction.
*/
public static void beginTransaction()
throws HibernateException {
Transaction tx = (Transaction) threadTransaction.get();
try {
if (tx == null) {
log.debug("Starting new database transaction in this thread.");
tx = getCurrentSession().beginTransaction();
threadTransaction.set(tx);
}
} catch (HibernateException ex) {
throw new HibernateException(ex);
}
}
/**
* Rollback the database transaction.
*/
public static void rollbackTransaction()
throws HibernateException {
Transaction tx = (Transaction) threadTransaction.get();
try {
threadTransaction.set(null);
if ( tx != null && !tx.wasCommitted() && !tx.wasRolledBack() ) {
log.debug("Tyring to rollback database transaction of this thread.");
tx.rollback();
}
} catch (HibernateException ex) {
throw new HibernateException(ex);
} finally {
closeSession();
}
}
Thanks
谢谢
采纳答案by Pascal Thivent
Check if your database supports a roll back i.e. if you're using InnoDB tables and not MyISAM (you can mix transactional and non-transactional tables but in most cases, you want all your tables to be InnoDB).
检查您的数据库是否支持回滚,即您是否使用 InnoDB 表而不是 MyISAM(您可以混合事务表和非事务表,但在大多数情况下,您希望所有表都是 InnoDB)。
回答by Kdeveloper
MySQL by default uses the MyIsam storage engine. As the MyISAM does not support transactions, insert, update and delete statements are directly written to the database. The commit and rollback statements are ignored.
MySQL 默认使用 MyIsam 存储引擎。由于 MyISAM 不支持事务,insert、update 和 delete 语句直接写入数据库。提交和回滚语句被忽略。
In order to use transaction you need to change the storage engine of you tables. Use this command:
为了使用事务,您需要更改表的存储引擎。使用这个命令:
ALTER TABLE table_name ENGINE = InnoDB;
ALTER TABLE table_name ENGINE = InnoDB;
(note how ever, that the two storage engines are different and you need to test you're application if it still behaves as expected)
(请注意,这两个存储引擎是不同的,如果它仍然按预期运行,您需要测试您的应用程序)