0

以前我在我的应用程序中使用了 JDBC,它运行得非常快,但是我已经修改它以使用 Hibernate,这使得它太慢了,尤其是当它需要打开一个包含下拉框的页面时。与 JDBC 相比,打开此类页面需要更长的时间。

如果我尝试使用外键访问表,则需要更长的时间。

我的服务器是 GlassFish,我正在使用以下版本的休眠。

  <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-core</artifactId>
            <version>4.1.10.Final</version>
            <type>jar</type>
        </dependency>

问题是为什么它比 JDBC 慢,我需要在每个 session.beginTransaction() 之前有以下 lin 吗?

    session = HibernateUtil.getSessionFactory().openSession();

以以下为例,它有一个下拉框,需要在打开页面后填充。

HibernateUtil.java

package com.myproject.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;

    private static SessionFactory configureSessionFactory() {
        try {
            System.out.println("1");

            Configuration configuration = new Configuration();
            configuration.configure();
            serviceRegistry = new 
                ServiceRegistryBuilder()
                  .applySettings(configuration.getProperties())
                  .buildServiceRegistry();
            System.out.println("2");

            sessionFactory = configuration.buildSessionFactory(serviceRegistry);
            System.out.println("3");

            return sessionFactory;
        } catch (HibernateException e) {
            System.out.append("** Exception in SessionFactory **");
            e.printStackTrace();
        }
        return sessionFactory;
    }

    public static SessionFactory getSessionFactory() {
        return configureSessionFactory();
    }
}

MyClassModel.java

public class MyClassModel extends HibernateUtil {

    private Session session;

     public Map populatedropdownList() {
        Map map = new HashMap();
        session = HibernateUtil.getSessionFactory().openSession();
        session.beginTransaction();
        List<MyListResult> temp = null;
        try{

              temp = retrieveItems();
              System.err.println("size:" + temp.size());
              for(int i=0;i<temp.size();i++){
                  map.put(temp.get(i).getId(),temp.get(i).getName());
              }
        session.getTransaction().commit();
        session.close();
        return map;
    }catch(Exception e){
        e.printStackTrace();
    }
    return map;
   }



private List <MyListResult> retrieveItems(){
              Criteria criteria = session.createCriteria(MyTable.class, "MyTable");
                ProjectionList pl = Projections.projectionList();
                pl.add(Projections.property("MyTable.id").as("id"));
                pl.add(Projections.property("MyTable.name").as("name"));
                criteria.setProjection(pl);

                criteria.setResultTransformer(new 
                        AliasToBeanResultTransformer(MyListResult.class));
                return criteria.list();
    }

MyListResult.java

public class MyListResult implements Serializable {
    private int id;
    private String Name;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return Name;
    }

    public void setName(String Name) {
        this.Name = Name;
    }    

}

休眠.cfg.xml

<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
        "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">

<hibernate-configuration>

    <session-factory>

        <!-- Database connection settings -->
        <property name="connection.driver_class">
            com.mysql.jdbc.Driver
        </property>
        <property name="connection.url">
            jdbc:mysql://localhost:3306/MyDatabase
        </property>
        <property name="connection.username">root</property>
        <property name="connection.password"></property>

        <!-- JDBC connection pool (use the built-in) -->
        <property name="connection.pool_size">1</property>

        <!-- SQL dialect -->
        <property name="dialect">
            org.hibernate.dialect.MySQLDialect
        </property>

        <!-- Enable Hibernate's automatic session context management -->
        <property name="current_session_context_class">thread</property>

        <!-- Disable the second-level cache  -->
        <property name="cache.provider_class">
            org.hibernate.cache.NoCacheProvider
        </property>

        <!-- Echo all executed SQL to stdout -->
        <property name="show_sql">true</property>

        <!-- Drop and re-create the database schema on startup -->
        <property name="hbm2ddl.auto">update</property>

                <mapping class="com.MyProject.MyTable" />


    </session-factory>

</hibernate-configuration>

控制台如下

INFO: in myform
INFO: 1
INFO: HHH000043: Configuring from resource: /hibernate.cfg.xml
INFO: HHH000040: Configuration resource: /hibernate.cfg.xml
INFO: HHH000041: Configured SessionFactory: null
INFO: 2
INFO: HHH000402: Using Hibernate built-in connection pool (not for production use!)
INFO: HHH000115: Hibernate connection pool size: 1
INFO: HHH000006: Autocommit mode: false
INFO: HHH000401: using driver [com.mysql.jdbc.Driver] at URL 
[jdbc:mysql://localhost:3306/MyDatabase]
INFO: HHH000046: Connection properties: {user=root, password=****}
INFO: HHH000400: Using dialect: org.hibernate.dialect.MySQLDialect
INFO: HHH000399: Using default transaction strategy (direct JDBC transactions)
INFO: HHH000397: Using ASTQueryTranslatorFactory
INFO: HHH000228: Running hbm2ddl schema update
INFO: HHH000102: Fetching database metadata
INFO: HHH000396: Updating schema
INFO: HHH000261: Table found: MyDatabase.MyTable
INFO: HHH000037: Columns: [id, name, age, xx, yy]
INFO: HHH000126: Indexes: [primary]
INFO: HHH000232: Schema update complete
INFO: Hibernate: select this_.id as y0_, this_.name as y1_ from MyTable this_
SEVERE: size:4
4

2 回答 2

1

通常在应用程序中,您不应该在每次需要会话时都构建会话工厂。这就是应用程序使用休眠时实际需要的。如果您想手动管理会话,那么您编写HibernateUtil使其成为单例。最初,在静态初始化程序块中构建会话工厂

  private static final ThreadLocal<Session> threadLocal = new ThreadLocal<>();
  private static SessionFactory sessionFactory;

  static {
    try {
      sessionFactory = configureSessionFactory();
    } catch (Exception e) {
      System.err.println("%%%% Error Creating SessionFactory %%%%");
      e.printStackTrace();
    }
  }

  private HibernateUtil() {
  }

  public static SessionFactory getSessionFactory() {
    return sessionFactory;
  }

  public static Session getSession() throws HibernateException {
    Session session = threadLocal.get();

    if (session == null || !session.isOpen()) {
      if (sessionFactory == null) {
        rebuildSessionFactory();
      }
      session = (sessionFactory != null) ? sessionFactory.openSession() : null;
      threadLocal.set(session);
    }

    return session;
  }

  public static void rebuildSessionFactory() {
    try {
      sessionFactory = configureSessionFactory();
    } catch (Exception e) {
      System.err.println("%%%% Error Creating SessionFactory %%%%");
      e.printStackTrace();
    }
  }

  public static void closeSession() throws HibernateException {
    Session session = (Session) threadLocal.get();
    threadLocal.set(null);

    if (session != null) {
      session.close();
    }
  }

认为这足以添加到您的代码来运行您的应用程序。

于 2013-06-20T10:03:04.340 回答
0

虽然我对 Hibernate 没有任何直接经验,但我使用的是 NHibernate,它是在 Java 版本之后建模的,所以这应该仍然是正确的......

建立SessionFactory需要时间,更何况,如果我正确地阅读了配置,那么当它启动时,你会让它检查你的模型和数据库之间的模式变化。

相反,您应该做的是SessionFactory在启动时创建一次(或在第一次使用数据访问时,取决于您何时想要支付设置 Hibernate 的成本)并在应用程序的整个生命周期中使用它。

我倾向于做的事情大致是这样的(粗略的伪代码,因为我的 Java 生锈了):

Session getSession()
{
    if(sessionFactory == null)
       buildSessionFactory()

    return sessionFactory.OpenSession()
}

(当然,这并没有考虑到任何可能的线程竞争条件)。这应该有望看到相当大的性能提升。请记住,由于额外的映射层,ORM 几乎永远不会像手工编码的 SQL 那样快,但它是性能和易于编码之间的权衡。

于 2013-06-20T04:56:19.583 回答