Hibernate java.lang.OutOfMemoryError:Java堆空间
我有一个在Tomcat 7上运行的Java Web应用程序 – jdk1.7
此应用程序使用Spring 4.1.5.RELEASE和Hibernate 4.2.2.Final
我的问题是建筑部分工厂的堆空间的OutOfMemoryException
这是我打开SessionFactory的静态方法
public class GenericDAO { public static SessionFactory sessionFactory = null; public static ServiceRegistry serviceRegistry = null; Transaction tx = null; public static SessionFactory createSessionFactory() { Configuration configuration = new Configuration(); configuration.configure(); serviceRegistry = new ServiceRegistryBuilder().applySettings( configuration.getProperties()). buildServiceRegistry(); sessionFactory = configuration.buildSessionFactory(serviceRegistry); return sessionFactory; } }
这是DAO的一个例子
public class SpecificDAO extends GenericDAO { public int save(MyObject item) { Session session = createSessionFactory().openSession(); try { tx = session.beginTransaction(); session.save(item); tx.commit(); return item.getId(); } catch (HibernateException e) { if (tx != null) tx.rollback(); e.printStackTrace(); } finally { session.close(); } return -1; } }
错误发生在包含的行
sessionFactory = configuration.buildSessionFactory(serviceRegistry);
问题不会在部署时立即发生,而是在使用2到3天后发生
这是我的Hibernate.cfg.xml
jdbc:sqlserver://192.168.XX.XXX:1433;databaseName=DatabaseName com.microsoft.sqlserver.jdbc.SQLServerDriver username password <!-- update -->
您必须只创建一次会话工厂,因为它是一个重量级的对象,请参阅hibernate文档了解其详细信息。
以下是doc应如何创建的示例代码:
import org.hibernate.SessionFactory; import org.hibernate.boot.registry.StandardServiceRegistryBuilder; import org.hibernate.cfg.Configuration; public class HibernateUtil { private static final SessionFactory sessionFactory = buildSessionFactory(); private static SessionFactory buildSessionFactory() { try { // Create the SessionFactory from hibernate.cfg.xml return new Configuration().configure().buildSessionFactory( new StandardServiceRegistryBuilder().build() ); } catch (Throwable ex) { // Make sure you log the exception, as it might be swallowed System.err.println("Initial SessionFactory creation failed." + ex); throw new ExceptionInInitializerError(ex); } } public static SessionFactory getSessionFactory() { return sessionFactory; } }
最好在使用后刷新和清除会话,您可以同时使用它们
session.flush(); session.clear();
有关link1和link2的更多信息
您正在为每个save()调用创建一个SessionFactory对象。
即您为每个save()调用重复创建一个新的SessionFactory但不关闭内存中的现有SessionFactory对象。
调用save()多少次? 同样没有SessionFactory将在内存中,这会导致内存泄漏。
SessionFactory是重量级对象,因此您可以在应用程序初始化时创建。 您可以创建SingleTon来实例化SessionFactory。
避免在每个DAO操作上实例化SessionFactory对象。 它非常慢并导致内存泄漏。 在这个答案中更好地解释
如果您仍在使用Spring
,最好委托Spring
使用SessionFactory,事务和处理SQLexception。 例如,save()方法将减少到一行代码sessionFactory.getCurrentSession().save(item);
手动事务打开/提交/回滚应替换为@Transactional
属性。 此外,通常更好地将事务放在整个服务方法上,而不是放在每个DAO方法上,但它取决于业务逻辑。
这里的示例如何配置Spring上下文以使用Hibernate
(只是谷歌的第一篇文章)
我稍微采用了这个例子来解决当前的问题
@Repository public class SpecificDAO { private SessionFactory sessionFactory; @Autowired public SpecificDAO(SessionFactory sessionFactory) { this.sessionFactory = sessionFactory; } @Transactional(propagation=Propagation.REQUIRED) public int save(MyObject item) { try{ sessionFactory.getCurrentSession().save(item); }catch (HibernateException e) { return -1; } } }
弹簧配置
it.company.client.project.hibernate.MyObject
org.hibernate.dialect.SQLServerDialect org.hibernate.connection.DatasourceConnectionProvider false