在使用Hibernate是遇到了这样一个问题:
当在servlet中调用DAO的save方法并提交事务后,控制台显示已经执行了sql语句,但是却没有向数据库中记录,如果把数据库的隔离级别设置为未提交读,这是可以看见刚插入的记录,但是之前已经调用了提交事务的语句,这是为什么呢?
注:主键生成策略为“native”,数据库是MySQL。
[b]问题补充:[/b]
已经把数据库操作放到了事务中,而当第二条记录提交的时候才会向数据库中插入第一条记录,而新提交的记录不会被插入。
[b]问题补充:[/b]
[code="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();
}
[/code]
把你的Servlet和Dao中取得Hibernate Session的方式多换成Session session = HibernateSessionFactory.getSession(); (如果你的HibernateSessionFactory类中没有getSession方法,你自己用MyEclipse去生成一个,在添加Hibernate框架是会自动创建这个类的),在Dao里不要关闭session,session都放到你调用Dao的方法中去关闭。
你可以先试一下下面这个修改
[code="java"]
UserDAO userDAO = new UserDAO();
User user = new User();
[color=red] Session session = HibernateSessionFactory.getSession(); [/color]
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();
}
[/code]
你看看事务真的提交了吗?
MySQL未提交读:允许脏读,也就是可能读取到其他会话中未提交事务修改的数据
MySQL的默认隔离机制为可重复读
默认应该是读取提交数据,
锁定查询中使用的所有数据以防止其他用户更新数据,但是其他用户可以将新的幻像行插入数据集,且幻像行包括在当前事务的后续读取中,
所以就是会产生这种现象,
隔离级别 脏读(Dirty Read) 不可重复读(NonRepeatable Read) 幻读(Phantom Read)
读未提交(Read uncommitted) 可能 可能 可能
读已提交(Read committed) 不可能 可能 可能
可重复读(Repeatable read) 不可能 不可能 可能
可串行化(Serializable ) 不可能 不可能 不可能
建议你在执行对数据操作的时候,将相关的操作放到一个事务中来执行,这样可以保存事务的完整性。
如果你使用的Dao代码是通过MyEclipse自动生成的,那么在Dao的方法里没有添加事务,你需要自己添加,或者是用openSessionInView方式。如果你用到Spring,那你可以通过在spring配置文件中通声明事务的方式来做(自己看spring参考手册)。一般情况下你不需要自己去修改数据库的事务级别。
把你的servlet方法和调用的Dao代码贴出来。
你提交事务的时候,根本就没有得到当前的事务。
把你的代码:
try {
tx = session.beginTransaction();
userDAO.save(user);
[color=orange] tx.commit(); [/color]
}
改成
try {
tx = session.beginTransaction();
userDAO.save(user);
[color=orange] tx.getTransaction().commit(); [/color]
}
试一下,这样看行不。