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() の前に次の行が必要なのかということです。

    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
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 を直接使用した経験はありませんが、Java バージョンをモデルにした NHibernate を使用しているので、これはまだ正しいはずです...

SessionFactory構成を正しく読んでいれば、起動時にモデルとデータベース間のスキーマの変更をチェックする必要があるため、構築には時間がかかります。

代わりにすべきことはSessionFactory、起動時 (または、Hibernate の設定コストを支払うタイミングに応じて、データ アクセスの最初の使用時) に 1 回作成し、それをアプリの有効期間を通じて使用することです。

私がする傾向があるのは、大まかに次のようなことです (私の Java はさびているので、大まかな疑似コードです):

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

    return sessionFactory.OpenSession()
}

(もちろん、これはスレッド化で起こりうる競合状態を考慮していません)。これにより、パフォーマンスが大幅に向上することが期待されます。ORM は、マッピング層が追加されているため、手動でコーディングされた SQL ほど高速ではありませんが、パフォーマンスとコーディングの容易さとの間のトレードオフであることに注意してください。

于 2013-06-20T04:56:19.583 に答える