java 在我的应用程序中打开和关闭 SessionFactory 的位置
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/30096416/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Where to open and where to close SessionFactory in my Application
提问by Sri
I am developing jsf application and using hibernate as back end. I want create session factory and close it once through out application. I am creating Session factory with util class.
我正在开发 jsf 应用程序并使用 hibernate 作为后端。我想创建会话工厂并在整个应用程序中关闭它。我正在使用 util 类创建会话工厂。
import org.hibernate.HibernateException;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.service.ServiceRegistryBuilder;
public class HibernateUtil
{
private static SessionFactory sessionFactory;
private static ServiceRegistry serviceRegistry;
static
{
try
{
Configuration configuration = new Configuration().configure();
serviceRegistry = new ServiceRegistryBuilder().applySettings(configuration.getProperties()).buildServiceRegistry();
sessionFactory = configuration.buildSessionFactory(serviceRegistry);
}
catch (HibernateException he)
{
System.err.println("Error creating Session: " + he);
throw new ExceptionInInitializerError(he);
}
}
public static SessionFactory getSessionFactory()
{
return sessionFactory;
}
}
public static void closeFactory() {
if (sessionFactory != null) {
try {
sessionFactory.close();
} catch (HibernateException ignored) {
log.error("Couldn't close SessionFactory", ignored);
}
}
}
In my every method of DAO classes I am opening session factory and closing it. So where i can open/close the session factory only once for application. Thanks in advance.
在我的 DAO 类的每个方法中,我打开会话工厂并关闭它。所以我只能在应用程序中打开/关闭会话工厂一次。提前致谢。
采纳答案by subhakar patnala
Where to open and where to close SessionFactory in my Application
在我的应用程序中打开和关闭 SessionFactory 的位置
You are using singleton session factory object. So you can call the getSessionFactory() method with class name. So that you do need to create object for session factory every time.
您正在使用单例会话工厂对象。因此,您可以使用类名调用 getSessionFactory() 方法。所以你每次都需要为会话工厂创建对象。
Your DAO class methods should like this
你的 DAO 类方法应该是这样的
Method in DAO class
DAO 类中的方法
public boolean createUser(NewUserDTO newUserDTO) {
try {
sessionFactory = DBUtils.getSessionFactory();
session = sessionFactory.openSession();
transaction = session.beginTransaction();
session.save(newUserDTO);
session.getTransaction().commit();
} catch (RuntimeException runtimeException) {
LOGGER.error(runtimeException);
transaction.rollback();
return false;
} finally {
if (session != null) {
session.close();
}
}
return true;
}
And session must be closed for every method. So that you are not creating session factory for every class.
并且必须为每种方法关闭会话。这样您就不会为每个班级创建会话工厂。
回答by Serge Ballesta
The rule is that you should have one and only one SessionFactory throughout your application.
规则是在整个应用程序中应该只有一个 SessionFactory。
Where to open and close it depends on what the application is :
在哪里打开和关闭它取决于应用程序是什么:
- for a classicapplication, it would be opened and closed in main.
- for a web application it would be opened and closed in a ServletContextListener (respectively in contextInitialized and contextDestroyed events)
- 对于经典应用程序,它将在 main 中打开和关闭。
- 对于 Web 应用程序,它将在 ServletContextListener 中打开和关闭(分别在 contextInitialized 和 contextDestroyed 事件中)
You can also use a singleton and create it in static method as you do and close it at the end like above.
您也可以像上面一样使用单例并在静态方法中创建它并在最后关闭它。
But please do not close the session factoryat the end of a DAO method.
但是请不要在 DAO 方法结束时关闭会话工厂。
For Sessions, you get one at the beginning of a unit of workthrough openSession
, and close it after commit or rollback (in case of exception you must rollback and immediately close the session). But Hibernate manual states : The scope of a Hibernate org.hibernate.Session is flexible but you should never design your application to use a new Hibernate org.hibernate.Session for every database operation. Even though it is used in the following examples, consider session-per-operation an anti-pattern.
对于会话,您在工作单元开始时通过获得一个openSession
,并在提交或回滚后关闭它(如果出现异常,您必须回滚并立即关闭会话)。但是 Hibernate 手册指出:Hibernate org.hibernate.Session 的范围是灵活的,但您永远不应将应用程序设计为对每个数据库操作使用新的 Hibernate org.hibernate.Session。尽管在以下示例中使用了它,但请将 session-per-operation 视为一种反模式。
Normally, you will use one single session per what needs a transaction. For example in a Web application, session per request is a common design.
通常,您将针对每个需要事务的内容使用一个会话。例如,在 Web 应用程序中,每个请求的会话是一种常见的设计。
But you could also use a higher level framework like Spring, that will do all SessionFactory and Session management for you.
但是您也可以使用更高级别的框架,如 Spring,它将为您完成所有 SessionFactory 和 Session 管理。
回答by OO7
SessionFactory:The job of SessionFactory is to handle all the sessions in the application. Generally, there is only one sessionFactoryin the application which allows to create as many as sessionsrequired to perform CRUD operations.
SessionFactory:SessionFactory的工作是处理应用程序中的所有会话。通常,应用程序中只有一个 sessionFactory允许创建执行 CRUD 操作所需的会话。
SessionFactory is immutable & threadsafe.Therefore multiple threads can access the same sessionFactory object.
SessionFactory 是不可变的和线程安全的。因此多个线程可以访问同一个 sessionFactory 对象。
static {
try {
Configuration configuration = new Configuration().configure("hibernate.cfg.xml");
serviceRegistry = new StandardServiceRegistryBuilder().applySettings(
configuration.getProperties()).build();
sessionFactory = auditConfiguration.buildSessionFactory(serviceRegistry);
} catch (Throwable ex) {
System.err.println("Initial SessionFactory creation failed." + ex);
throw new ExceptionInInitializerError(ex);
}
}
Session:Session is a light weight and a non-threadsafeobject. Hence, session cannot be shared between multiple threads. It should be created for every transaction on DBeither Create, Read, Update or Delete & must be closed when transaction is done.
Session:Session 是一个轻量级的非线程安全对象。因此,会话不能在多个线程之间共享。它应该为 DB 上的每个事务创建,无论是创建、读取、更新还是删除,并且在事务完成时必须关闭。
try {
Session session = sessionFactory.openSession();
// do some CRUD operation
} catch(Exception ex) {
// On error, revert all changes done
if (transaction != null) {
transaction.rollback();
}
} finally {
if (session != null) {
session.close();
}
}
So I suggest u to open/close session
instead of sessionFactory
.
所以我建议你打开/关闭session
而不是sessionFactory
.
回答by AnirbanDebnath
The best way is by using ThreadLocal
.
最好的方法是使用ThreadLocal
.
public class MyUtil {
private static SessionFactory sessionFactory;
private static ServiceRegistry serviceRegistry;
private static final ThreadLocal<Session> threadLocal;
static {
try {
Configuration configuration = new Configuration();
configuration.configure();
serviceRegistry = new StandardServiceRegistryBuilder().applySettings(configuration.getProperties()).build();
sessionFactory = configuration.buildSessionFactory(serviceRegistry);
threadLocal = new ThreadLocal<Session>();
} catch(Throwable t){
t.printStackTrace();
throw new ExceptionInInitializerError(t);
}
}
public static Session getSession() {
Session session = threadLocal.get();
if(session == null){
session = sessionFactory.openSession();
threadLocal.set(session);
}
return session;
}
public static void closeSession() {
Session session = threadLocal.get();
if(session != null){
session.close();
threadLocal.set(null);
}
}
public static void closeSessionFactory() {
sessionFactory.close();
StandardServiceRegistryBuilder.destroy(serviceRegistry);
}
}
Here, the SessionFactory
is initialized only once using the static
block.
Hence, whenever the main
class makes a call to getSession()
, the presence of Session object is first checked in the threadLocal
object.
Therefore, this program provides thread-safety.
After each operation, closeSession()
will close the session and set the threadLocal
object to null.
Finally call the closeSessionFactory()
.
在这里,SessionFactory
仅使用static
块初始化一次。因此,每当main
类调用 时getSession()
,都会首先检查对象中是否存在 SessionthreadLocal
对象。因此,该程序提供线程安全性。每次操作后,closeSession()
都会关闭会话并将threadLocal
对象设置为空。最后调用closeSessionFactory()
.
回答by Andreas D?rrenb?cher
its not enough to close the session. You must additonally close the factory.
这不足以结束会议。您必须另外关闭工厂。
session.close();
session.getSessionFactory().close();
回答by underdog
So where i can open/close the session factory only once for application.
所以我只能在应用程序中打开/关闭会话工厂一次。
A session factory is instantiated only once per application & gets destroyed when the app shuts down. A session factory is a factory of session so it's setup only once.
会话工厂每个应用程序仅实例化一次,并在应用程序关闭时被销毁。会话工厂是会话工厂,因此它只设置一次。
Regarding sessions, you should open & close a session in every method. You should not have too many open sessions.
关于会话,您应该在每种方法中打开和关闭会话。你不应该有太多的开放会话。
So its a must that you close the session after the transaction.
因此,您必须在交易后关闭会话。
When you don't close your Hibernate sessions and therefore do not release JDBC connections after every transaction, you have what is typically called Connection leak. So, after a number of requests (depending on the size of your connection pool) the server will not be able to acquire a connection to respond your request. Actually, server will be waiting for connections to be released and be available on pool again and it will seem to be hanging.
当您不关闭 Hibernate 会话并因此不在每次事务后释放 JDBC 连接时,您就会遇到通常称为连接泄漏的情况。因此,在多次请求(取决于您的连接池的大小)之后,服务器将无法获得连接来响应您的请求。实际上,服务器将等待连接被释放并再次在池中可用,并且它似乎正在挂起。