java - hibernate 问题 `SessionFactory`

标签 java multithreading hibernate servlets sessionfactory

我有一个 JSP、Servlet(纯 JSP、Servlet)应用程序,它使用 Hibernate。下面是一个表的 Hibernate 实现类。

DesignationImpl.java

package dao;

import model.sub.DesigAllBean;
import java.util.List;
import model.main.Designation;
import org.hibernate.Query;
import org.hibernate.SQLQuery;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.Configuration;

/**
 *
 * @author Yohan
 */
public class DesignationImpl implements DesignationInterface
{


    @Override
    public Session openCurrentSession() {
            Session currentSession = getSessionFactory().openSession();
            return currentSession;
    }

    @Override
    public Transaction openTransaction(Session session) {
        Transaction beginTransaction = session.beginTransaction();
        return beginTransaction;
    }

    private static SessionFactory getSessionFactory() {

        Configuration configuration = new Configuration().configure();
        StandardServiceRegistryBuilder builder = new StandardServiceRegistryBuilder()
                        .applySettings(configuration.getProperties());
        SessionFactory sessionFactory = configuration.buildSessionFactory(builder.build());
        return sessionFactory;
    }

    @Override
    public void save(Designation d, Session session)
    {
        session.save(d);
    }

    @Override
    public void update(Designation d, Session session) 
    {
        session.update(d);
    }
}

下面是调用上述类的服务类。

DesignationService.java

package service;

import dao.Common;
import model.sub.*;
import dao.DesignationImpl;
import dao.DesignationInterface;
import java.util.ArrayList;
import java.util.List;
import model.main.Designation;
import org.hibernate.Session;
import org.hibernate.Transaction;

/**
 *
 * @author Yohan
 */
public class DesignationService 
{
    private DesignationInterface designationInterface;

    public DesignationService()
    {
        designationInterface = new DesignationImpl();
    }

    public Session getSession()
    {
        Session session = designationInterface.openCurrentSession();
        return session;
    }

    public Transaction getTransaction(Session session)
    {
        return designationInterface.openTransaction(session);
    }

    public String save(Designation d)
    {
        Session session = designationInterface.openCurrentSession();
        Transaction transaction = null;
        String result="";

        try
        {
            transaction = designationInterface.openTransaction(session);
            designationInterface.save(d,session);
            transaction.commit();
            result = Common.SAVE_SUCCESS;
        }
        catch(Exception e)
        {
            e.printStackTrace();

            if(transaction!=null)
            {
                transaction.rollback();
            }
            result = Common.SAVE_ROLLBACK;
        }
        finally
        {
            session.close();
        }

        return result;
    }

    public String update(Designation d)
    {
        Session session = designationInterface.openCurrentSession();
        Transaction transaction = null;
        String result="";

        try
        {
            transaction = designationInterface.openTransaction(session);
            designationInterface.update(d,session);
            transaction.commit();
            result = Common.SAVE_SUCCESS;
        }
        catch(Exception e)
        {
            e.printStackTrace();

            if(transaction!=null)
            {
                transaction.rollback();
            }
            result = Common.SAVE_ROLLBACK;
        }
        finally
        {
            session.close();
        }

        return result;
    }
}

servlet 如下调用它们。

DesignationService desigSrvc=new DesignationService();

        Designation designation=desigSrvc.findByForiegnKey(idEmployee);

        Employee empl=new Employee();
        empl.setIdEmployee(idEmployee);

        if(designation.getDateCreated()==null)
        {
            designation.setDateCreated(Common.getCurrentDateSQL());
        }   

        designation.setEmployee(empl);
        designation.setDesignation(txtDesignation);
        designation.setLocation(location);
        designation.setSalary(salary);
        designation.setDatePromoted(datePromoted);
        designation.setLastUpdated(Common.getCurrentDateSQL());       

        desigSrvc.save(designation);

如您所见,那里发生了一件坏事,即 servlet 每次执行时都会创建新的 SessionFactory 实例。我有 Driver#Connect 问题,我想这可能就是原因。

我阅读了 stackoverflow 帖子,其中一些帖子似乎建议整个应用程序仅使用一个 SessionFactory。如果合适的话我该怎么做呢?也许制作一个像下面这样的单例类并在我的实现类中使用它?

public class SessionFactoryBuilder
{
    private static SessionFactoryBuilder instance;
    private static SessionFactory sessionFactory;

    private SessionFactoryBuilder()
    {
    }

    private static void buildConfig()
    {
        Configuration configuration = new Configuration().configure();
            StandardServiceRegistryBuilder builder = new StandardServiceRegistryBuilder()
                            .applySettings(configuration.getProperties());
            sessionFactory = configuration.buildSessionFactory(builder.build());
    }

    public static SessionFactoryBuilder getInstance()
    {
         if(instance == null) 
         {
            instance = new SessionFactoryBuilder();
            buildConfig();
         }
      return instance;
    }

    public SessionFactory getSessionFactory()
    {
        return sessionFactory;
    }
}

那么线程呢? Servlet 是多线程的,不是吗?

最佳答案

正如我所评论的,我将 HibernateUtil.java 类作为 Singleton。这个类可以使用 HibernateUtil.getSessionFactory() 为您提供 sessionfactory,您应该从您的 DesignationImpl 类中删除相关代码

public class HibernateUtil {

private static StandardServiceRegistry serviceRegistry; 
private static SessionFactory INSTANCE = null;
public static SessionFactory getSessionFactory() {
     if(INSTANCE=null){
          createSessionFactory():
      }
      return sessionFactory;
}
private synchronized static void createSessionFactory(){
    if(INSTANCE!=null){return;}
    Configuration configuration = new Configuration();
    configuration.configure();
    SeviceRegistry=newStandardServiceRegistryBuilder().applySettings(configuration.getProperties()).build();
    sessionFactory = configuration.buildSessionFactory(serviceRegistry);
    }
  }
}

找到上面的代码,并请建议/评论以确认代码的正确性。我认为使用此代码可以处理线程。我添加了双重检查以避免创建多个 sessionfactory ,并且它是一个繁重的资源。

关于java - hibernate 问题 `SessionFactory`,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29465685/

相关文章:

java - Android:向位图添加填充

java - JRE 模拟库中不存在方法 'Iterable.forEach(Consumer<? super T>)'

objective-c - zlib:线程安全的zalloc和zfree在C中?

java - 从文本中提取矩形中的单词

c# - 在 UI 线程上运行代码但在当前线程上调用回调?

android - 中断 IntentService

java - 数据库中的表不与外键连接

hibernate - 使用 Hibernate 3.6.3 和 JPA 2.0 创建类型化查询时出现 AbstractMethodError

java - 为什么 Hibernate 会抛出 org.hibernate.exception.LockAcquisitionException?

java - JDBC 在使用 LOAD DATA LOCAL INFILE 时是否有相对路径选项?