在Java Hibernate中,当我们需要对DB做一些事情时,我们需要: 1.公开会议 2.开始交易 3.完成交易 4.关闭会话
例如,如果我想获得学生列表:
public static List<Student> getStudentList()
{
List<Student> l = null;
Session session = HibernateUtil.getSessionFactory().openSession();
try {
String hql = "from Student";
Query query = session.createQuery(hql);
l = query.list();
} catch (HibernateException ex) {
//Log the exception
System.err.println(ex);
} finally {
session.close();
}
return l;
}
插入学生
public static boolean addStudent(Student s)
{
Session session = HibernateUtil.getSessionFactory().openSession();
if (... /* check if student is already exists*/)
{
return false;
}
Transaction transaction = null;
try {
transaction = session.beginTransaction();
session.save(s);
transaction.commit();
} catch (HibernateException ex) {
//Log the exception
transaction.rollback();
System.err.println(ex);
} finally {
session.close();
}
return true;
}
为什么getStudentList()中没有事务?提前谢谢
答案 0 :(得分:0)
这个hibernate article解释了未在事务中显式执行的SELECT操作的行为。
本文给出了以下示例,但对于您的查询示例也是如此。
Session session = sessionFactory.openSession();
session.get(Item.class,123l);
session.close();
- 打开一个新会话。此时它不会获得数据库连接。
- 对get()的调用会触发SQL SELECT。 Session现在从连接池获取JDBC连接。默认情况下,Hibernate会立即使用setAutoCommit(false)关闭此连接上的自动提交模式。这有效地启动了JDBC事务!
- SELECT在此JDBC事务中执行。会话关闭,连接返回到池并由Hibernate释放 - Hibernate在JDBC Connection上调用close()。未提交的交易会发生什么?
醇>该问题的答案是,“它取决于!”在连接上调用close()时,JDBC规范没有提及有关挂起事务的任何信息。发生的情况取决于供应商如何实施规范。例如,使用Oracle JDBC驱动程序,对close()的调用将提交事务!当JDBC Connection对象关闭并且资源返回到池时,大多数其他JDBC供应商采用相同的路由并回滚任何挂起的事务。 显然,这对SELECT [...]
来说不是问题
让我们扩展上面的例子以引发可能的问题。
Session session = sessionFactory.openSession();
Item item = session.get(Item.class, 123l);
item.setPrice(10);
session.close();
现在,如果Item
的新价格持续存在,它依赖于JDBC驱动程序。
因此,只要没有数据库更改,即使JDBC驱动程序将回滚事务,您也可以忽略纯SELECT
操作的开始和提交事务。
但无论如何,我强烈建议在任何操作中使用交易以避免误解和问题。