0

スタンドアロンのスレッド アプリケーションがあります。これはメッセージを待っているリスナーであり、メッセージが到着すると、メッセージをDBに保存する必要がある何かを行います。しかし、アプリケーションを実行して「手動でメッセージを送信」するとすべてが正常に機能するため、問題がありますが、アプリケーションを実行してシステムのメッセージを待つと (たとえば、メッセージが到着してから 1 時間後)、APP が実行されます。シンクするDBに保存するには、次のように伝えます。

java.sql.SQLException: Io 例外: 接続のリセットまたは java.sql.BatchUpdateException: Io 例外: 接続のリセット

C3p0 0.9.2.1 で Hibernate 3.2.6 を使用しています

セッションの構成は次のとおりです。

public final class PersistenceUtil{
    private static final SessionFactory sessionFactory;

    static {
        try {
            String location = ServiceLocator.getInstance().getConfigurationService().getProperty("adaptor.location");
            if (LOC_1.equals(location)) {
                sessionFactory = new AnnotationConfiguration().configure("hibernate.1.cfg.xml").buildSessionFactory();
            } else if(LOC_2.equals(location)) {
                sessionFactory = new AnnotationConfiguration().configure("hibernate.2.cfg.xml").buildSessionFactory();
            }else {
                sessionFactory = new AnnotationConfiguration().configure().buildSessionFactory();
            }
            sessionFactory.openSession();
        } catch (Throwable ex) {
            throw new ExceptionInInitializerError(ex);
        }
    }


    private PersistenceUtil() {
    }

    public static void shutdown() {
        try {
            sessionFactory.close();
        } catch (HibernateException e) {
            LOG.error("PersistanceUtil.shutdown Error: " + e.getMessage());
        }

    }

    public static SessionFactory getSessionFactory() {
        return sessionFactory;
    }

保存したいときは(そしてエラーはどこにありますか):

public T save(T entity) {

        if (!getSession().getTransaction().isActive()) {
            log.warn("Session not active. Starting the session");
            getSession().beginTransaction();
        }

        getSession().save(entity);
        getSession().getTransaction().commit();
        return entity;
    }

そして、私の hibernate.cfg.xml は次のとおりです。

<hibernate-configuration>
    <session-factory>
        <!-- Database connection settings -->
        <property name="connection.driver_class">oracle.jdbc.driver.OracleDriver</property>
        <property name="connection.url">URL</property>
        <property name="connection.username">USER</property>
        <property name="connection.password">Password</property>

        <!-- SQL dialect -->
        <property name="dialect">org.hibernate.dialect.Oracle10gDialect</property>
        <!-- <property name="hibernate.hbm2ddl.auto">update</property> -->
        <!-- Enable Hibernate's automatic session context management -->
        <property name="current_session_context_class">thread</property>
        <property name="hibernate.transaction.factory_class">org.hibernate.transaction.JDBCTransactionFactory</property>
        <!-- Echo all executed SQL to stdout -->
        <property name="show_sql">true</property>
        <property name="hibernate.c3p0.min_size">1</property>
        <property name="hibernate.c3p0.max_size">100</property>
        <property name="hibernate.c3p0.timeout">3000</property>
        <property name="hibernate.c3p0.max_statements">0</property>
        <property name="hibernate.c3p0.idle_test_period">0</property>

        <mapping class="MessageEO" />
        <mapping class="CustomerEO" />

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

私は何を間違っていますか?前もって感謝します

4

1 に答える 1

1

データを保存する前に、新しいセッションを作成してみませんか? Hibernate のドキュメントによると、これはアトミック操作の適切なアプローチです。コードでコメントを見ることができるように、トランザクションを開始することは、新しいセッションを開始すること、または新しい接続を開くことを意味すると考えていますが、これは正しくありません。セッションごとに複数の (常にネストされているとは限りません) トランザクションを持つことができます。私は常にアトミック操作に次のテンプレートを使用しています。決してがっかりすることはありません。私はEclipseのテンプレートとしてこのコードを持っています:

Session session = HibernateUtil.getSessionFactory().openSession();
    Transaction tx = null;
    try {
        tx = session.beginTransaction();
        // save/ update / delete your entities here
        tx.commit();
    } catch (RuntimeException ex) {
        if (tx != null) {
            tx.rollback();
        }
        throw ex;
    } finally {
        session.close();
    }

原則:

  1. 単一のSessionFactoryオブジェクトを保持します。作成には費用がかかります。
  2. 一括操作 (保存、変更など) ごとに、または単一のエンティティに対して、ファクトリを使用して新しいセッションを開きます。これは軽量でスレッド セーフです。
  3. セッション自体はスレッドセーフではありません。
  4. 常に新しいトランザクションを開始し、必要に応じてそれらをロール コミット/ロールバックします。読み取り専用のデータ フェッチの場合でも。
  5. 一括操作が完了したら、必ずセッションを閉じます (接続の解放など)。
  6. 例外が発生したセッションで同じセッションを使用しないでください。
于 2013-11-05T08:17:11.620 に答える