我正在开发一个webapp,并且在Hibernate抛出异常后我遇到了连接错误:
com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: No operations allowed after connection closed.
每次在发生异常后尝试访问我的数据库时,它都给了我这个例外。
我现在Hibernate不应该抛出错误,如果我的应用程序编码良好但是如果与db的连接发生了某些事情,我不希望我的应用程序遇到这个错误。
这是我的HibernateUtil类:
public class HibernateUtil {
private static Logger log = Logger.getLogger(HibernateUtil.class);
private static org.hibernate.SessionFactory sessionFactory;
private static String confFile = "hibernate-test.properties";
private static final ThreadLocal<Session> threadSession = new ThreadLocal<Session>();
private HibernateUtil() {
}
public static void buildSessionFactory(){
Configuration configuration = new Configuration();
synchronized(HibernateUtil.class){
if(sessionFactory == null){
try {
Properties properties = new Properties();
properties.load(HibernateUtil.class.getClassLoader().getResourceAsStream(confFile));
configuration.setProperties(properties);
} catch (Exception e) {
log.fatal("cannot load the specified hibernate properties file: " + confFile);
throw new RuntimeException("cannot load the specified hibernate properties file : " + confFile, e);
}
sessionFactory = configuration.configure().buildSessionFactory();
}
HibernatePBEEncryptorRegistry registry = HibernatePBEEncryptorRegistry.getInstance();
if(registry.getPBEStringEncryptor("strongHibernateStringEncryptor") == null) {
StandardPBEStringEncryptor strongEncryptor = new StandardPBEStringEncryptor();
strongEncryptor.setAlgorithm("PBEWithMD5AndDES"); // not really needed as it is the default
strongEncryptor.setPassword("aStrongPassword");
registry.registerPBEStringEncryptor("strongHibernateStringEncryptor", strongEncryptor);
}
}
}
public static SessionFactory getSessionFactory() {
if(sessionFactory == null){
buildSessionFactory();
}
return sessionFactory;
}
public static Session getCurrentSession(){
if(!getSessionFactory().getCurrentSession().isOpen())
getSessionFactory().openSession();
return getSessionFactory().getCurrentSession();
}
}
这是我的BaseAction类,其中设置了会话的初始化和关闭:
public class BaseAction extends ActionSupport {
public Session hib_session;
public void initHibSession() {
hib_session = HibernateUtil.getCurrentSession();
hib_session.beginTransaction();
hib_session.clear();
}
public void closeHibSession() {
hib_session.getTransaction().commit();
}
}
以下是一个动作示例:
Transaction transaction = new Transaction(user, Transaction.Type.REGISTRATION, new HashSet(domains));
initHibSession();
hib_session.save(transaction);
closeHibSession();
transaction_id = transaction.getId();
有没有办法避免上面的例外?
答案 0 :(得分:1)
每次我发生异常后尝试访问我的数据库时,它都给了我这个例外。
我不确定了解具体情况。无论如何,在异常之后,您应该回滚事务,关闭会话并重新开始。话虽这么说,我对你的代码有一些评论。
关于HibernateUtil
:
为什么你有一个ThreadLocal
,Session#getCurrentSession()
方法处理对象(你似乎没有使用本地线程)。
在HibernateUtil.getCurrentSession()
中,为什么会混淆getCurrentSession()
和openSession()
?首先,您无需执行操作,如果没有session
与当前线程关联,getCurrentSession()
将返回新的session
。其次,两种方法都不同,并且具有不同的语义(您需要在使用openSession()
时自己关闭session
),您应该使用其中一种。
关于BaseAction
:
clear()
Session#beginTransaction()
之后会话Open Session in View。如果您没有提交正在进行的交易,您将丢失所有待处理的更改。这真的是你想要的吗?PS:我会考虑使用Sessions and transactions模式从代码中消除所有这些负担。