1

これは私の処女の質問なので、ここに行きます...アイデアは、データベーステーブルに対して多数の更新ステートメントを実行しているということです。SQLでは、単純 です。これらは何百万もあるため、これらのいくつかをまとめてバッチ処理することをお勧めします。私はここの指示に従いました: http://docs.jboss.org/hibernate/orm/3.3/reference/en-US/html/batch.html と、スタックオーバーフローや他の場所でランダムに見つけた他のいくつかのページですが、すべて同じように読みます。私の考えは、読み取りを行うのではなく、更新のみを直接行い、次のようにループし続けることでした。 update table_name set col1 = 123 where col2 = 456 and col1 is null


  sessionFactory = new Configuration().configure("finaldetail/hibernate.dev.cfg.xml") 
          .addPackage("com.xxx.app.ftm.domain.event").addAnnotatedClass(FinalTrainDetail.class) 
          .addAnnotatedClass(AbstractDetail.class).addAnnotatedClassFinalTrainDetailWork.class).buildSessionFactory();
      inputStream = new BufferedReader(new FileReader(new File(args[0])));
      session = sessionFactory.openSession();
      transaction = session.beginTransaction(); 
      String s; 
      int count = 0; 
      while ((s = inputStream.readLine()) != null) {
        Query query = session.createQuery("update FinalTrainDetail  detail set detail.trainSummary "
                + "=:summaryId where detail.trainDetail=:detailId and detail.trainSummary=null"); 
        query.setParameter("summaryId", new Long(s.substring(9, 18)));
        query.setParameter("detailId", new Long(s.substring(0, 9)));
        query.executeUpdate();
        count++; 
        if (count % 20 == 0) { 
          log.debug("should commit"); 
          session.flush(); 
          session.clear(); 
        } 
      } 
      transaction.commit();
      System.out.println("exit");
    } catch (IOException e) {
      transaction.rollback();
      log.error(e.toString());
    } catch (Throwable t) {
      System.out.print(t);
      log.error("exception caught during Updateing Offline", t);
      System.exit(2);
    } finally {
      if (inputStream != null)
        inputStream.close();
      session.close();
    }

したがって、ここでの理解は、フラッシュによって 20 回の更新ごとにコミットが行われ、クリアによって第 1 レベルのキャッシュが空になり、OutOfMemory 例外が回避されるということです。

これまでのところ、私が持っている設定

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

<hibernate-configuration>
  <session-factory>
    <!-- SQL dialect -->
    <property name="dialect">org.hibernate.dialect.Oracle10gDialect</property> 

    <!-- Database connection settings --> 
    <property name="connection.driver_class">oracle.jdbc.driver.OracleDriver</property> 
    <property name="connection.url">jdbc:oracle:thin:@dev264.oracle.XXXX.com:1521:DEV264</property>
    <property name="connection.username">XXXX</property>
    <property name="connection.password">XXX</property>
    <property name="connection.shutdown">true</property>

    <!-- JDBC connection pool (use the built-in one) -->
    <property name="connection.pool_size">1</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>

    <!-- disable batching so HSQLDB will propagate errors correctly. -->
    <property name="jdbc.batch_size">20</property> 

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

  </session-factory>
</hibernate-configuration>

Show sql は、デバッグ目的で有効になっています。だから、log4jに設定したとき、私が得られない、または見えないのは

<logger name="org.hibernate.transaction">
    <level value="debug"/>
    <appender-ref ref="file"/>
    <appender-ref ref="console"/>
</logger>

しか見えない

[DEBUG] [main] [org.hibernate.transaction.JDBCTransaction] [commit] 
[DEBUG] [main] [org.hibernate.transaction.JDBCTransaction] [commit] 
[DEBUG] [main] [org.hibernate.transaction.JDBCTransaction] [commit] 

ログファイルの最後にあり、「フラッシュ」が発生しているときには発生しません。だから私が疑問に思っているのは、コミットが本当に20レコードごとに呼び出されているのか、メモリ内にあまりにも多くのオブジェクトを構築しているのか、何十万ものテストレコードがないため、これを実行すると本番環境で OutOfMemory が発生するのかということです.

4

2 に答える 2