2017-01-26 1 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); 

나는 시간이 좀 후에 일어나는 시작 것으로 나타났습니다. 바람둥이를 재시작하거나 앱을 재배포하면 문제가 사라집니다.

+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); 

시작도 없기 때문에 당신은 활성 트랜잭션을 얻을 수 없습니다 : 그것은 당신이 당신이 그것을 호출하는 오류를 얻고있는 이유. 이에 코드를 변경합니다

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

왜 비 관리되는 환경에서 트랜잭션을 시작하는 올바른 것은 이것은 Documentation of Hibernate에서입니다 : getTransaction()의 문서에 따라

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

은 현재 세션하지 않습니다 거래를 시작했습니다. 트랜잭션 11.2 Database Transaction demarcation 시작 왜 여기

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

그리고는 다음과 같습니다

데이터베이스, 또는 시스템을, 트랜잭션 경계들은 항상 필수적이다. 데이터베이스와의 통신은 데이터베이스 트랜잭션 (이 경우는 자동 커밋 모드에 익숙한 많은 개발자를 혼란스럽게합니다) 외부에서 발생할 수 있습니다. 읽기 전용 작업 인 경우에도 항상 명확한 트랜잭션 경계를 사용하십시오.

그리고 당신의 DB에 잠금 장치가 많이 발생하기 때문에 긴 트랜잭션을 갖는는 DB에 대한 나쁜, Session and transaction scopes 데이터베이스 트랜잭션이되어야합니다, 데이터베이스에서 잠금 경합을 줄이기 위해

가능한 한 짧게 긴 데이터베이스 트랜잭션 을 사용하면 응용 프로그램이 매우 동시적인 로드로 조정되지 않습니다. 작업 단위 (UOW)가 완료 될 때까지 사용자가 생각하는 동안 데이터베이스 트랜잭션을 으로 열어 두지 않는 것이 좋습니다.

+0

나는 당신이 나의 질문을 보았을 때, 트랜잭션을 시작했는데, 당신은 또한 이것을 볼 것이다 :'transaction = session.beginTransaction();' – pedja

+0

그러나 시작하기 전에'transaction = session.getTransaction();' 그래서 오류가 발생했습니다. – Gatusko

+0

아니요,'getTransaction'이 아닌'session.get'에 오류가 있습니다. – pedja