将JDBC更改为hibernate后,应用程序运行速度非常慢

时间:2013-06-20 04:29:45

标签: java hibernate java-ee struts2 hibernate-mapping

以前我在我的应用程序中使用了JDBC并且它运行得非常快,但是我已经修改它以使用Hibernate,这使得它太慢,特别是当它需要打开一个带有下拉框的页面时。与JDBC相比,打开这种页面需要更长的时间。

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

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

  <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;
    }    

}

hibernate.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

2 个答案:

答案 0 :(得分:1)

通常在应用程序中,每次需要会话时都不应构建会话工厂。这就是应用程序实际需要使用hibernate的东西。如果要手动管理会话,则编写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();
    }
  }

认为您的代码足以添加到您的应用程序中。

答案 1 :(得分:0)

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

构建SessionFactory需要时间,尤其是如果我正在阅读正确的配置,那么在启动时,您需要检查模型与数据库之间的架构更改。

你应该做的是在启动时创建SessionFactory一次(或者在第一次使用数据访问时,根据你想要支付设置Hibernate的成本的时间)并在生命周期中使用它你的应用。

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

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

    return sessionFactory.OpenSession()
}

(当然,这并未考虑任何可能的线程竞争条件)。希望看到相当大的性能提升。请记住,由于额外的映射层,ORM几乎从未像手工编写的SQL一样快,但它是性能和编码简易性之间的折衷。