问题描述
- SSH-hibernate4.3.8-HibernateSessionFactory.java
-
初学者问题:
1)web开发,哪里有靠谱的HibernateSessionFactory.java 及其对应的hibernate.cfg.xml?感觉自己手上的这两个文件的问题多多,各种debug,很耗时间
2) hibernate的jar包要放WEB-INF/lib目录下?又或者跟hibernate.cfg.xml里面的某个property的设置有关?sever一开始起不来,网上搜了下,把hibernate的jar包要放WEB-INF/lib目录下,server就可以起来了。奇怪,struts的jar放WEB-INF/lib目录下可以理解,怎么hibernate的也要放在这个目录下?
开发环境
eclipse: Luna Service Release 1a (4.4.1)
mysql: 5.6
struts: 2.3.20hibernate: 4.3.8
现象:
第一次从web访问,正常。说明struts, mysql工作都是正常的。
第二次起从web访问,报下面的错误。
将下面的代码注释掉后,再从web访问,每次正常了。问题是:一直不close SessionFactory 不会有问题吗? 是否要优化HibernateSessionFactory.java?HibernateTestAction.java
//sf.close(); 即SessionFactory一直不close
Debug - execute - after getSessionFactory Debug - execute - throw exception at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:201) at org.hibernate.internal.AbstractSessionImpl.getJdbcConnectionAccess(AbstractSessionImpl.java:341) at org.hibernate.engine.jdbc.internal.JdbcCoordinatorImpl.<init>(JdbcCoordinatorImpl.java:114) at org.hibernate.engine.transaction.internal.TransactionCoordinatorImpl.<init>(TransactionCoordinatorImpl.java:89) at org.hibernate.internal.SessionImpl.<init>(SessionImpl.java:258)
代码:
HibernateSessionFactory.javapackage hibernate; import org.hibernate.HibernateException; import org.hibernate.Interceptor; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.cfg.Configuration; import org.hibernate.boot.registry.StandardServiceRegistry; import org.hibernate.boot.registry.StandardServiceRegistryBuilder; /** * Configures and provides access to Hibernate sessions, tied to the current * thread of execution. Follows the Thread Local Session pattern, see * {@link http://hibernate.org/42.html }. */ public class HibernateSessionFactory { private static final SessionFactory sessionFactory = buildSessionFactory(); private static SessionFactory buildSessionFactory() { System.out.println("sessionFactory - on buildSessionFactory"); try { Configuration cfg = new Configuration().configure(); StandardServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder() .applySettings(cfg.getProperties()).build(); SessionFactory sessionFactory = cfg.buildSessionFactory(serviceRegistry); return sessionFactory; } catch (Throwable ex) { // Make sure you log the exception, as it might be swallowed System.out.println("Initial SessionFactory creation failed." + ex); throw new ExceptionInInitializerError(ex); } } public static SessionFactory getSessionFactory() { System.out.println("sessionFactory - on getSessionFactory"); if (sessionFactory == null) System.out.println("build sessionFactory - fail"); else System.out.println("build sessionFactory - succe"); return sessionFactory; } }
hibernate.cfg.xml
<?xml version='1.0' encoding='UTF-8'?> <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd"> <!-- Generated by MyEclipse Hibernate Tools. --> <hibernate-configuration> <session-factory> <!-- <property name="hibernate.transaction.factory_class"> org.hibernate.transaction.JTATransactionFactory </property> <property name="cache.provider_class">org.hibernate.cache.internal.NoCacheProvider</property> --> <property name="cache.use_query_cache">true</property> <property name="cache.provider_class">org.hibernate.cache.HashtableCacheProvider</property> <property name="cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</property> <property name="connection.username">root</property> <property name="connection.password">admin</property> <property name="connection.url"> jdbc:mysql://localhost:3306/db_database10 </property> <property name="dialect"> org.hibernate.dialect.MySQLDialect </property> <property name="cache.use_query_cache">true</property> <property name="cache.provider_class"> org.hibernate.cache.HashtableCacheProvider </property> <property name="show_sql">true</property> <property name="connection.driver_class"> com.mysql.jdbc.Driver </property> <mapping resource="mapping.xml" /> </session-factory> </hibernate-configuration>
HibernateTestAction.java
public class HibernateTestAction extends ActionSupport implements ModelDriven<Book> { ... public String execute() { SessionFactory sf = HibernateSessionFactory.getSessionFactory(); try { System.out.println("Debug - execute - after getSessionFactory "); Session s = sf.openSession(); s.beginTransaction(); System.out.println("Debug - execute - after beginTransaction "); String hql = "from Book"; Query query; query = s.createQuery(hql); List<Book> books = query.list(); dataMap.put("data", books); System.out.println("Debug - execute - query.list "); for(Book bookTemp: books) { System.out.println(bookTemp.toString()); } s.getTransaction().commit(); System.out.println("Debug - execute - after commit"); s.close(); } catch (Exception e) { // TODO Auto-generated catch block System.out.println("Debug - execute - throw exception "); e.printStackTrace(); } sf.close(); dataMap.put("status", "SUCCESS"); return SUCCESS; } ... }
解决方案
我们一般采用spring来管理sessionFactory,如果用hibernate自己管理的话开发最好用单例模式创建sessionFactory,
sessionFactory只创建一次就可以,是不需要关闭的。因为session是线程不安全的,所以每次用hibenate的时候记得要
及时关闭session,即每次查询操作数据库的时候需要sessionFactory来openSession,每次操作完数据库或者查询完数据库
要记得及时close掉session就可以了。
如果你看过你的server的文件结构你就明白为什么所有jar包都放在WEB-INF/lib下,WEB-INF下放着你的所有的代码, 你的所有Java代码被编译成
classes文件放在了WEB-INF/classes中相当于src,所有jar包放在WEB-INF/jar下,WEB-INF中还有web.xml配置文件,WEB-INF外面放页面,相当于webroot
如果你觉得DEBUG多多,一个是删掉你的代码中的sysout,一个不显示你的sql语句,从hibernate.cfg.xml中
true中true改成false,一个是你是不是放hibernate包放进去日志包log4j系列,如果是就修改你的
log4j.properties文件,把里面的log4j.rootLogger=DEBUG改成log4j.rootLogger=info就可以大大减少你的DEBUG输出了。
解决方案二:
谢谢 kunkunqianqian。
用下面的HibernateSessionFactoryV1.java,问题解决了
package hibernate;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.boot.registry.StandardServiceRegistry;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.Configuration;
/**
* Configures and provides access to Hibernate sessions, tied to the
* current thread of execution. Follows the Thread Local Session
* pattern, see {@link http://hibernate.org/42.html }.
*/
public class HibernateSessionFactoryV1 {
/**
* Location of hibernate.cfg.xml file.
* Location should be on the classpath as Hibernate uses
* #resourceAsStream style lookup for its configuration file.
* The default classpath location of the hibernate config file is
* in the default package. Use #setConfigFile() to update
* the location of the configuration file for the current session.
*/
private static final ThreadLocal<Session> threadLocal = new ThreadLocal<Session>();
private static org.hibernate.SessionFactory sessionFactory;
private static Configuration configuration = new Configuration();
private static String CONFIG_FILE_LOCATION = "/hibernate.cfg.xml";
private static String configFile = CONFIG_FILE_LOCATION;
static {
try {
configuration.configure(configFile);
StandardServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder()
.applySettings(configuration.getProperties()).build();
sessionFactory = configuration.buildSessionFactory(serviceRegistry);
} catch (Exception e) {
System.err.println("%%%% Error Creating SessionFactory %%%%");
e.printStackTrace();
}
}
private HibernateSessionFactoryV1() {
}
/**
* Returns the ThreadLocal Session instance. Lazy initialize
* the <code>SessionFactory</code> if needed.
*
* @return Session
* @throws HibernateException
*/
public static Session getSession() throws HibernateException {
System.out.println("Debug - on HibernateSessionFactoryV1.getSession ");
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;
}
/**
* Rebuild hibernate session factory
*
*/
public static void rebuildSessionFactory() {
try {
configuration.configure(configFile);
StandardServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder()
.applySettings(configuration.getProperties()).build();
sessionFactory = configuration.buildSessionFactory(serviceRegistry);
} catch (Exception e) {
System.err.println("%%%% Error Creating SessionFactory %%%%");
e.printStackTrace();
}
}
/**
* Close the single hibernate session instance.
*
* @throws HibernateException
*/
public static void closeSession() throws HibernateException {
Session session = (Session) threadLocal.get();
threadLocal.set(null);
if (session != null) {
session.close();
}
}
/**
* return session factory
*
*/
public static org.hibernate.SessionFactory getSessionFactory() {
return sessionFactory;
}
/**
* return session factory
*
* session factory will be rebuilded in the next call
*/
public static void setConfigFile(String configFile) {
HibernateSessionFactoryV1.configFile = configFile;
sessionFactory = null;
}
/**
* return hibernate configuration
*
*/
public static Configuration getConfiguration() {
return configuration;
}
}