2017-01-26 7 views
6

トランザクションを手動で開始してもこのエラーが発生します。 HibernateUtilsgetは有効なトランザクションなしで有効ではありません - 休止状態5

public class HibernateUtil 
{ 
private static final SessionFactory sessionFactory; 

static 
{ 
    try 
    { 
     // Create the SessionFactory from hibernate.cfg.xml 
     Configuration config = new Configuration().configure(); 
     config.setProperty("hibernate.show_sql", String.valueOf(ConfigManager.getInstance().getBoolean(Consts.CONFIG_DB_SHOW_SQL, false))); 
     config.setProperty("hibernate.format_sql", String.valueOf(ConfigManager.getInstance().getBoolean(Consts.CONFIG_DB_FORMAT_SQL, false))); 

     config.setProperty("hibernate.dialect", ConfigManager.getInstance().getString(Consts.CONFIG_DB_DIALECT, "org.hibernate.dialect.MySQLDialect")); 
     config.setProperty("hibernate.connection.driver_class", ConfigManager.getInstance().getString(Consts.CONFIG_DB_DRIVER_CLASS, "com.mysql.jdbc.Driver")); 
     config.setProperty("hibernate.connection.url", ConfigManager.getInstance().getString(Consts.CONFIG_DB_URL, "jdbc:mysql://localhost/photometo")); 
     config.setProperty("hibernate.connection.useUnicode", "true"); 
     config.setProperty("hibernate.connection.characterEncoding", "UTF-8"); 
     config.setProperty("hibernate.connection.username", ConfigManager.getInstance().getString(Consts.CONFIG_DB_USERNAME, "root")); 
     config.setProperty("hibernate.connection.password", ConfigManager.getInstance().getString(Consts.CONFIG_DB_PASSWORD, "")); 
     config.setProperty("hibernate.hbm2ddl.auto", ConfigManager.getInstance().getString(Consts.CONFIG_DB_HBMDDL_AUTO, "update")); 
     sessionFactory = config.buildSessionFactory(); 
    } 
    catch (Throwable ex) 
    { 
     throw new ExceptionInInitializerError(ex); 
    } 
} 

public static SessionFactory getSessionFactory() 
{ 
    return sessionFactory; 
} 

} 

<property name="hibernate.connection.autoReconnect">true</property> 

    <!-- Use the C3P0 connection pool. --> 
    <property name="hibernate.c3p0.min_size">5</property> 
    <property name="hibernate.c3p0.max_size">20</property> 
    <property name="hibernate.c3p0.timeout">300</property> 
    <property name="hibernate.c3p0.max_statements">50</property> 
    <property name="hibernate.c3p0.idle_test_period">3000</property> 

    <!-- Disable second-level cache. --> 
    <property name="cache.provider_class">org.hibernate.cache.NoCacheProvider</property> 
    <property name="cache.use_query_cache">false</property> 
    <property name="cache.use_minimal_puts">false</property> 
    <property name="max_fetch_depth">3</property> 

    <!-- Bind the getCurrentSession() method to the thread. --> 
    <property name="current_session_context_class">thread</property> 

    <property name="hibernate.jdbc.batch_size">30</property> 

hibernate.cfg.xml

Session session = HibernateUtil.getSessionFactory().getCurrentSession(); 
transaction = session.getTransaction(); 
if(!transaction.isActive()) 
{ 
    transaction = session.beginTransaction(); 
} 

accessToken = session.get(OAuthAccessToken.class, token); 

は、私は、これはいくつかの時間後に起こって開始することに気づきました。私がTomcatを再起動したり、アプリケーションを再デプロイしたりすると、問題が解消する

+1

設定が正常になっています。 githubで問題を実証できるコードの実行可能な最小限のバージョンをプッシュすることは可能ですか?または少なくともスタックトレースを質問に追加してください。 – skadya

答えて

2

あなたは決してトランザクションを開始せず、他のトランザクションを取得することはできません。そのため、あなたはそれを呼び出すときにエラーが発生します:

Session session = HibernateUtil.getSessionFactory().getCurrentSession(); 
    transaction = session.getTransaction(); // Here is the error! You can't get an active transaction, becasue there isn't even started 
    if(!transaction.isActive()) // transaction.isActive() is usually for closing a transction in the end 
    { 
     transaction = session.beginTransaction(); // You are starting the transaction! 
    } 

accessToken = session.get(OAuthAccessToken.class, token); 

開始されていないため、アクティブなトランザクションを取得することはできません。非管理された環境でのトランザクションを開始する理由は正しいが、Documentation of Hibernateからこれです

// Non-managed environment idiom with getCurrentSession() 
try { 
    factory.getCurrentSession().beginTransaction(); 

    // do some work 
    ... 

    factory.getCurrentSession().getTransaction().commit(); 
} 
catch (RuntimeException e) { 
    factory.getCurrentSession().getTransaction().rollback(); 
    throw e; // or display error message 
} 

:これにコードを変更

// Non-managed environment idiom with getCurrentSession() 
try { 
    factory.getCurrentSession().beginTransaction(); 

    // do some work 
    ... 

    factory.getCurrentSession().getTransaction().commit(); 
} 
catch (RuntimeException e) { 
    factory.getCurrentSession().getTransaction().rollback(); 
    throw e; // or display error message 
} 

// Non-managed environment idiom with getCurrentSession() try { 
    factory.getCurrentSession().beginTransaction(); 

    // do some work 
    ... 

    factory.getCurrentSession().getTransaction().commit(); } catch (RuntimeException e) { 
    factory.getCurrentSession().getTransaction().rollback(); 
    throw e; // or display error message } 

getTransaction()のドキュメンテーションに続いて、現在のセッションにはありませんトランザクションを開始しました。

getTransaction() 
     Get the Transaction instance associated with this session. 

そして、ここで取引11.2 Database Transaction demarcation始める理由です:

データベース、またはシステムを、トランザクションの境界は、常に必要です。 データベースとの通信は、データベース のトランザクション外で行うことができます(これは、 自動コミットモードに慣れている多くの開発者を混乱させるようです)。 の読み取り専用操作に対しても、常に明確なトランザクション境界を使用します。

そして、あなたのDB内のロックの多くを生成しているため、長いトランザクションを持つことは、DBのために悪いです、Session and transaction scopesデータベース トランザクションがなければならない、データベース内のロックの競合を減らすために

可能な限り短い。長いデータベーストランザクション を使用すると、アプリケーションのスケーラビリティが並行して最大でも になるのを防ぐことができます。作業単位が完了するまで、ユーザーの思考時間中にデータベーストランザクションを開いておくことはお勧めしません( )。

+0

私はトランザクションを開始しました。あなたが私の質問を見ると、これも表示されます: 'transaction = session.beginTransaction();' – pedja

+0

しかし、トランザクションを開始する前に 'transaction = session.getTransaction();'その理由はエラーです。 – Gatusko

+0

いいえ、 'session.get'では' getTransaction'ではなくエラーがスローされます – pedja

関連する問題