写这篇博客的原因是出于昨天我在问答频道的一个问题,该问题如下:
当在servlet中调用DAO的save方法并提交事务后,控制台显示已经执行了sql语句,但是却没有向数据库中记录,如果把数据库的隔离级别设置为未提交读,这是可以看见刚插入的记录,但是之前已经调用了提交事务的语句,这是为什么呢?
注:主键生成策略为“native”,数据库是MySQL。
问题补充:
已经把数据库操作放到了事务中,而当第二条记录提交的时候才会向数据库中插入第一条记录,而新提交的记录不会被插入。
问题补充:
Java代码 ;
- UserDAO userDAO = new UserDAO();
- User user = new User();
- SessionFactory sessionFactory = HibernateSessionFactory.getSessionFactory();
- Session session = sessionFactory.openSession();
- Transaction tx = null;
- user.setUsername(registerForm.getUsername());
- user.setEmail(registerForm.getEmail());
- try {
- tx = session.beginTransaction();
- userDAO.save(user);
- tx.commit();
- }
- catch (RuntimeException e) {
- if (tx != null)
- tx.rollback();
- throw e;
- }
- finally {
- session.close();
- }
通过查看Hibernate的代码发现的其中的问题。
我在获得Session对象的时候采用的是 sessionFactory.openSession(); Hibernate会新产生一个Session对象,接着执行userDAO.save(user)语句,而UserDAO类的save方法中用到的Session是通过HibernateSessionFactory.getSession()方法获得的,再继续看HibernateSessionFactory,其getSession()方法如下
public static Session getSession() throws HibernateException { Session session = (Session) threadLocal.get(); if (session == null || !session.isOpen()) { if (sessionFactory == null) { rebuildSessionFactory(); } session = (sessionFactory != null) ? sessionFactory.openSession() : null; threadLocal.set(session); } return session; }
因此HibernateSessionFactory会为每个线程创建一个Session对象,MyEclipse所生成的DAO类就是用的这个
Session,这与在程序中通过openSession()方法所得到的是两个不同的Session对象,因此我在程序中调用的提交事务方法是在后一个Session中进行的,而对User对象的保存是在第一个Session中,而该Session中并没有执行提交事务操作。
但是,至于之前的为什么当我执行第二次插入操作时会把前一条记录插入的原因还没有弄清楚,哪位大哥知道,欢迎留言。