2015-12-28 6 views
3

Я пытаюсь использовать весну @Transactional аннотация и timeout параметр. Я в основном тестирую код с помощью кода Thread.sleep(). Затем я получаю исключение тайм-аута, как я ожидал. Также я хочу получить исключение тайм-аута, когда операции с базой данных занимают больше времени, чем мой период ожидания. Я блокирую запись в таблице в моей базе данных для утверждения выбора выбора. Я пытаюсь обновить эту запись. Но программа ждет и ничего не делает. Вот мой пример кода.Spring Transactional TimeOut

@Transactional(rollbackFor = Exception.class, timeout=5) 
public void executeService(List<sendData> list) throws Exception{ 
    List<sendData> newList = gDAO.updateSentList(list); 

} 

В этом случае программа должна исключить исключение таймаута. Как я могу это исправить?

+1

Этот вопрос похож на мою проблему, http://stackoverflow.com/questions/31876975/spring-transactional-timeout-not-working-as-expected –

+0

Какая система транзакций вы используете? – Betlista

+0

Я использую транзакционную систему JDBC для операций db. –

ответ

0

Я решил свою проблему с помощью oracle.jdbc.ReadTimeout=60000 от контекста приложения. @Transactional аннотация не работает в исключении таймаута чтения jdbc.

3

Наконец я нашел решение ...

Короткий ответ, что проблема заключается в том, как вы проверяете тайм-аут - Thread.sleep() не может быть использован ...

Длинный ответ:

Что я должен был использовать (потому что я тестировал с MySQL), было реальным заявлением - select sleep(5). Этот вызов завершился:

Exception in thread "main" org.hibernate.TransactionException: transaction timeout expired 
    at org.hibernate.engine.jdbc.internal.JdbcCoordinatorImpl.determineRemainingTransactionTimeOutPeriod(JdbcCoordinatorImpl.java:271) 
    at org.hibernate.engine.jdbc.internal.StatementPreparerImpl$StatementPreparationTemplate.setStatementTimeout(StatementPreparerImpl.java:208) 
    at org.hibernate.engine.jdbc.internal.StatementPreparerImpl$StatementPreparationTemplate.prepareStatement(StatementPreparerImpl.java:187) 
    at org.hibernate.engine.jdbc.internal.StatementPreparerImpl.prepareQueryStatement(StatementPreparerImpl.java:160) 
    at org.hibernate.loader.Loader.prepareQueryStatement(Loader.java:1885) 
    at org.hibernate.loader.Loader.executeQueryStatement(Loader.java:1862) 
    at org.hibernate.loader.Loader.executeQueryStatement(Loader.java:1839) 
    at org.hibernate.loader.Loader.doQuery(Loader.java:910) 
    at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:355) 
    at org.hibernate.loader.Loader.doList(Loader.java:2554) 
    at org.hibernate.loader.Loader.doList(Loader.java:2540) 
    at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2370) 
    at org.hibernate.loader.Loader.list(Loader.java:2365) 
    at org.hibernate.loader.custom.CustomLoader.list(CustomLoader.java:353) 
    at org.hibernate.internal.SessionImpl.listCustomQuery(SessionImpl.java:1909) 
    at org.hibernate.internal.AbstractSessionImpl.list(AbstractSessionImpl.java:311) 
    at org.hibernate.internal.SQLQueryImpl.list(SQLQueryImpl.java:141) 
    at org.hibernate.internal.AbstractQueryImpl.uniqueResult(AbstractQueryImpl.java:966) 
    at test.Dao.mysqlWait(Dao.java:41) 
    at test.Dao$$FastClassBySpringCGLIB$$bb93a016.invoke(<generated>) 
    at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204) 
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:720) 
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157) 
    at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:99) 
    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:281) 
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96) 
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) 
    at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:655) 
    at test.Dao$$EnhancerBySpringCGLIB$$da2836b3.mysqlWait(<generated>) 
    at test.Main.main(Main.java:16) 

Из стека это привлекло мое внимание: StatementPreparerImpl$StatementPreparationTemplate.setStatementTimeout(StatementPreparerImpl.java:208)

... так что я хотел бы попробовать с другим прецедентом

@Transactional(timeout=10) 
public void mysqlWait() { 
    System.out.println("timeout: " + sessionFactory.getCurrentSession().getTransaction().getTimeout()); 

    for (int i = 0; i < 6; i++) { 
     SQLQuery query = sessionFactory.getCurrentSession().createSQLQuery("select sleep(2)"); 
     System.out.println("executed (" + i + "): " + query.uniqueResult()); 
    } 
} 

и это привело:

Exception in thread "main" org.hibernate.exception.GenericJDBCException: could not extract ResultSet 
    at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:54) 
    at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:126) 
    at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:112) 
    at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.extract(ResultSetReturnImpl.java:91) 
    at org.hibernate.loader.Loader.getResultSet(Loader.java:2066) 
    at org.hibernate.loader.Loader.executeQueryStatement(Loader.java:1863) 
    at org.hibernate.loader.Loader.executeQueryStatement(Loader.java:1839) 
    at org.hibernate.loader.Loader.doQuery(Loader.java:910) 
    at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:355) 
    at org.hibernate.loader.Loader.doList(Loader.java:2554) 
    at org.hibernate.loader.Loader.doList(Loader.java:2540) 
    at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2370) 
    at org.hibernate.loader.Loader.list(Loader.java:2365) 
    at org.hibernate.loader.custom.CustomLoader.list(CustomLoader.java:353) 
    at org.hibernate.internal.SessionImpl.listCustomQuery(SessionImpl.java:1909) 
    at org.hibernate.internal.AbstractSessionImpl.list(AbstractSessionImpl.java:311) 
    at org.hibernate.internal.SQLQueryImpl.list(SQLQueryImpl.java:141) 
    at org.hibernate.internal.AbstractQueryImpl.uniqueResult(AbstractQueryImpl.java:966) 
    at test.Dao.mysqlWait(Dao.java:46) 
    at test.Dao$$FastClassBySpringCGLIB$$bb93a016.invoke(<generated>) 
    at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204) 
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:720) 
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157) 
    at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:99) 
    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:281) 
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96) 
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) 
    at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:655) 
    at test.Dao$$EnhancerBySpringCGLIB$$df6a7e0b.mysqlWait(<generated>) 
    at test.Main.main(Main.java:16) 
Caused by: com.mysql.jdbc.exceptions.MySQLTimeoutException: Statement cancelled due to timeout or client request 
    at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:1881) 
    at com.mysql.jdbc.PreparedStatement.executeQuery(PreparedStatement.java:1962) 
    at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.extract(ResultSetReturnImpl.java:82) 
    ... 26 more 

и в журнале также:

22:05:49.322 [main] DEBUG o.h.e.jdbc.spi.SqlExceptionHelper - could not extract ResultSet [n/a] 
com.mysql.jdbc.exceptions.MySQLTimeoutException: Statement cancelled due to timeout or client request 
    at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:1881) ~[mysql-connector-java-5.1.38.jar:5.1.38] 
    at com.mysql.jdbc.PreparedStatement.executeQuery(PreparedStatement.java:1962) ~[mysql-connector-java-5.1.38.jar:5.1.38] 
    at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.extract(ResultSetReturnImpl.java:82) ~[hibernate-core-4.3.11.Final.jar:4.3.11.Final] 
    at org.hibernate.loader.Loader.getResultSet(Loader.java:2066) [hibernate-core-4.3.11.Final.jar:4.3.11.Final] 
    at org.hibernate.loader.Loader.executeQueryStatement(Loader.java:1863) [hibernate-core-4.3.11.Final.jar:4.3.11.Final] 
    at org.hibernate.loader.Loader.executeQueryStatement(Loader.java:1839) [hibernate-core-4.3.11.Final.jar:4.3.11.Final] 
    at org.hibernate.loader.Loader.doQuery(Loader.java:910) [hibernate-core-4.3.11.Final.jar:4.3.11.Final] 
    at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:355) [hibernate-core-4.3.11.Final.jar:4.3.11.Final] 
    at org.hibernate.loader.Loader.doList(Loader.java:2554) [hibernate-core-4.3.11.Final.jar:4.3.11.Final] 
    at org.hibernate.loader.Loader.doList(Loader.java:2540) [hibernate-core-4.3.11.Final.jar:4.3.11.Final] 
    at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2370) [hibernate-core-4.3.11.Final.jar:4.3.11.Final] 
    at org.hibernate.loader.Loader.list(Loader.java:2365) [hibernate-core-4.3.11.Final.jar:4.3.11.Final] 
    at org.hibernate.loader.custom.CustomLoader.list(CustomLoader.java:353) [hibernate-core-4.3.11.Final.jar:4.3.11.Final] 
    at org.hibernate.internal.SessionImpl.listCustomQuery(SessionImpl.java:1909) [hibernate-core-4.3.11.Final.jar:4.3.11.Final] 
    at org.hibernate.internal.AbstractSessionImpl.list(AbstractSessionImpl.java:311) [hibernate-core-4.3.11.Final.jar:4.3.11.Final] 
    at org.hibernate.internal.SQLQueryImpl.list(SQLQueryImpl.java:141) [hibernate-core-4.3.11.Final.jar:4.3.11.Final] 
    at org.hibernate.internal.AbstractQueryImpl.uniqueResult(AbstractQueryImpl.java:966) [hibernate-core-4.3.11.Final.jar:4.3.11.Final] 
    at test.Dao.mysqlWait(Dao.java:46) [classes/:na] 
    at test.Dao$$FastClassBySpringCGLIB$$bb93a016.invoke(<generated>) [classes/:na] 
    at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204) [spring-core-4.2.4.RELEASE.jar:4.2.4.RELEASE] 
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:720) [spring-aop-4.2.4.RELEASE.jar:4.2.4.RELEASE] 
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157) [spring-aop-4.2.4.RELEASE.jar:4.2.4.RELEASE] 
    at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:99) [spring-tx-4.2.4.RELEASE.jar:4.2.4.RELEASE] 
    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:281) [spring-tx-4.2.4.RELEASE.jar:4.2.4.RELEASE] 
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96) [spring-tx-4.2.4.RELEASE.jar:4.2.4.RELEASE] 
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) [spring-aop-4.2.4.RELEASE.jar:4.2.4.RELEASE] 
    at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:655) [spring-aop-4.2.4.RELEASE.jar:4.2.4.RELEASE] 
    at test.Dao$$EnhancerBySpringCGLIB$$df6a7e0b.mysqlWait(<generated>) [classes/:na] 
    at test.Main.main(Main.java:16) [classes/:na] 

важной частью конфигурации пружины (не следует ожидать чего-то особенного):

<bean id="dataSource" 
    class="org.springframework.jdbc.datasource.DriverManagerDataSource"> 
    <property name="driverClassName" value="com.mysql.jdbc.Driver" /> 
    <property name="url" value="jdbc:mysql://localhost:3306/so" /> 
    <property name="username" value="root" /> 
    <property name="password" value="" /> 
</bean> 

<bean id="hibernateSessionFactory" 
    class="org.springframework.orm.hibernate4.LocalSessionFactoryBean"> 
    <property name="dataSource" ref="dataSource" /> 
    <property name="packagesToScan" value="test" /> 
    <property name="hibernateProperties"> 
     <props> 
      <prop key="hibernate.show_sql">true</prop> 
     </props> 
    </property> 
</bean> 

<tx:annotation-driven transaction-manager="txManager"/> 

<bean id="txManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager"> 
    <property name="sessionFactory" ref="hibernateSessionFactory" /> 
</bean> 
+0

У меня есть 'org.springframework.jdbc.datasource.DataSourceTransactionManager' bean и' org.springframework.jdbc.datasource.DriverManagerDataSource' и обработчик транзакций, основанный на аннотации, в моем контексте datasource. Я не использую спящий режим. Я протестировал этот случай с помощью «DBMS_LOCK.sleep (10);» и установил мой тайм-аут транзакции 5 секунд, но я не получил никакого исключения. Когда я отлаживаю код, если я жду или добавлю код thread.sleep, я получаю исключение тайм-аута. Время транзакции БД не влияет на мой таймаут транзакции. –

+0

Вот мой вопрос, как я undestand, но не JTS.hhttp: // stackoverflow.com/questions/7469661/how-jta-jts-handle-transaction-time-out-issue'. Является ли ответ строгим? Но как я могу контролировать эту проблему. –

+0

Если вы попробуете под кодом, возможно, вы столкнетесь с моей ситуацией. Я думаю, что время управления java только в java-коде. Это не учитывает время jdbc. @Transactional (timeout = 10) public void mysqlWait() { System.out.println ("timeout:" + sessionFactory.getCurrentSession(). GetTransaction(). GetTimeout()); SQLQuery query = sessionFactory.getCurrentSession().createSQLQuery ("select sleep (15)"); System.out.println ("Выполнено (" + i + "):" + query.uniqueResult()); } –