2017-02-21 51 views
0

私はHibernate(Spring 4.2.2 - Hibernate 4.3.6)を持つSpring MVCプロジェクトを持っています。 2つのデータソース(2つの異なるpostgresqlデータベース)を接続したいので、私はJTAの実装としてatomikosを使いました。私はすべての注釈での私の設定を持っているので、設定ファイルはこれです:Spring MVC複数のデータソース同じトランザクション内のJTA atomikos

@Configuration 
@PropertySource(value = { "classpath:hibernate.properties" }) 
public class HibernateConfig { 

    @Autowired 
    private Environment environment; 

    // First DB connection 
    @Primary 
    @Bean(name = "sessionFactory") 
    @DependsOn("setMyAtomikosSystemProps") 
    public LocalSessionFactoryBean sessionFactory() { 
    LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean(); 
    sessionFactory.setDataSource(dataSource()); 
    sessionFactory.setPackagesToScan(new String[] { "org.spring.model" }); 
    sessionFactory.setHibernateProperties(hibernateProperties()); 
    return sessionFactory; 
    } 

    @Bean(name = "statsSessionFactory") 
    @DependsOn("setMyAtomikosSystemProps") 
    public LocalSessionFactoryBean statsSessionFactory() { 
    LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean(); 
    sessionFactory.setDataSource(statsDataSource()); 
    sessionFactory.setPackagesToScan(new String[] { "org.spring.stats.model" }); 
    sessionFactory.setHibernateProperties(hibernateProperties()); 
    return sessionFactory; 
    } 

    @Primary 
    @Bean(name = "dataSource") 
    public DataSource dataSource() { 
    AtomikosDataSourceBean ds = new AtomikosDataSourceBean(); 
    ds.setUniqueResourceName("first"); 
    ds.setXaDataSourceClassName("org.postgresql.xa.PGXADataSource"); 
    ds.setXaProperties(dataSourceProperties("first")); 
    ds.setMinPoolSize(5); 
    ds.setMaxPoolSize(75); 
    ds.setMaxIdleTime(60 * 15); 
    return ds; 
    } 

    @Bean(name = "statsDataSource") 
    public DataSource statsDataSource() { 
    AtomikosDataSourceBean ds = new AtomikosDataSourceBean(); 
    ds.setUniqueResourceName("second"); 
    ds.setXaDataSourceClassName("org.postgresql.xa.PGXADataSource"); 
    ds.setXaProperties(dataSourceProperties("second")); 
    ds.setMinPoolSize(5); 
    ds.setMaxPoolSize(75); 
    ds.setMaxIdleTime(60 * 15); 
    return ds; 
    } 

    private Properties dataSourceProperties(String database) { 
    Properties p = new Properties(); 
    p.setProperty("user", environment.getRequiredProperty("hibernate.connection.username")); 
    p.setProperty("password", environment.getRequiredProperty("hibernate.connection.password")); 
    p.setProperty("serverName", environment.getRequiredProperty("hibernate.connection.url")) 
    p.setProperty("portNumber", environment.getRequiredProperty("hibernate.connection.port")) 
    p.setProperty("databaseName", database); 
    return p; 
    } 

    @Bean(name = "userTransactionService") 
    @DependsOn("setMyAtomikosSystemProps") 
    public UserTransactionService userTransactionService() { 
    UserTransactionServiceImp uts = new UserTransactionServiceImp(); 
    Properties prop = new Properties(); 
    prop.setProperty("com.atomikos.icatch.service", "com.atomikos.icatch.standalone.UserTransactionServiceFactory"); 
    uts.init(prop); 
    return uts; 
    } 

    @Bean 
    @DependsOn("userTransactionService") 
    public UserTransactionManager AtomikosTransactionManager() { 
    UserTransactionManager utm = new UserTransactionManager(); 
    utm.setForceShutdown(true); 
    utm.setStartupTransactionService(false); 
    return utm; 
    } 

    @Bean 
    @DependsOn("userTransactionService") 
    public UserTransaction AtomikosUserTransaction() { 
    UserTransactionImp ut = new UserTransactionImp(); 
    try { 
     ut.setTransactionTimeout(300); 
    } catch (SystemException e) { 
     e.printStackTrace(); 
    } 
    return ut; 
    } 

    @Bean 
    @DependsOn("userTransactionService") 
    public PlatformTransactionManager JtaTransactionManager() { 
    JtaTransactionManager jtaTM = new JtaTransactionManager(); 
    jtaTM.setTransactionManager(AtomikosTransactionManager()); 
    jtaTM.setUserTransaction(AtomikosUserTransaction()); 
    jtaTM.setAllowCustomIsolationLevels(true); 
    return jtaTM; 
    } 

    // SharedProperties 
    private Properties hibernateProperties() { 
    Properties properties = new Properties(); 
    properties.put("hibernate.dialect", environment.getRequiredProperty("hibernate.dialect")); 
    properties.put("hibernate.show_sql", environment.getRequiredProperty("hibernate.show_sql")); 
    properties.put("hibernate.format_sql", environment.getRequiredProperty("hibernate.format_sql")); 

    // JTA 
    properties.put("hibernate.current_session_context_class", "jta"); 
    properties.put("hibernate.transaction.factory_class", "org.hibernate.transaction.JTATransactionFactory"); 
    properties.put("hibernate.transaction.jta.platform", "com.atomikos.icatch.jta.hibernate4.AtomikosPlatform"); 
    return properties; 
    } 

    @Bean 
    public MethodInvokingFactoryBean setMyAtomikosSystemProps() { 
    MethodInvokingFactoryBean mifb = new MethodInvokingFactoryBean(); 
    Properties p = new Properties(); 
    p.setProperty("com.atomikos.icatch.hide_init_file_path", "true"); 
    p.setProperty("com.atomikos.icatch.no_file", "true"); 
    mifb.setArguments(new Object[] { p }); 
    mifb.setTargetObject(java.lang.System.getProperties()); 
    mifb.setTargetMethod("putAll"); 
    return mifb; 
    } 
} 

トランザクションが唯一のデータソースを必要とするが、私は両方からデータを取得したいと考えてサービスを作成した場合、私はこのエラーが発生した場合には、この構成では動作します:

GRAVE: Servlet.service() for servlet [dispatcher] in context with path [/api] threw exception [Request processing failed; nested exception is org.springframework.transaction.UnexpectedRollbackException: JTA transaction unexpectedly rolled back (maybe due to a timeout); nested exception is javax.transaction.RollbackException: Prepare: NO vote] with root cause 
com.atomikos.icatch.RollbackException: Prepare: NO vote 
    at com.atomikos.icatch.imp.ActiveStateHandler.prepare(ActiveStateHandler.java:202) 
    at com.atomikos.icatch.imp.CoordinatorImp.prepare(CoordinatorImp.java:523) 
    at com.atomikos.icatch.imp.CoordinatorImp.terminate(CoordinatorImp.java:687) 
    at com.atomikos.icatch.imp.CompositeTransactionImp.commit(CompositeTransactionImp.java:282) 
    at com.atomikos.icatch.jta.TransactionImp.commit(TransactionImp.java:172) 
    at com.atomikos.icatch.jta.TransactionManagerImp.commit(TransactionManagerImp.java:414) 
    at com.atomikos.icatch.jta.UserTransactionImp.commit(UserTransactionImp.java:86) 
    at org.springframework.transaction.jta.JtaTransactionManager.doCommit(JtaTransactionManager.java:1021) 
    at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:761) 
    at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:730) 
    at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:485) 
    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:291) 
    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.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207) 
    at com.sun.proxy.$Proxy91.findById(Unknown Source) 

しかし、応答が数秒で発生するため、これはタイムアウトの問題ではありません。

私はまた、非常に長いエラーのリストをpostgresから受け取っています。私は、エラーを「フィルタリング」しています:

WARN XAResourceTransaction - XA resource 'second': rollback for XID '3139322E3136382E322E322E746D313438373639323737373736333030303032:3139322E3136382E322E322E746D32' raised -4: the supplied XID is invalid for this XA resource 
org.postgresql.xa.PGXAException: Errore durante il «rollback» di una transazione preparata 

(この1つはイタリア語であり、それは準備されたトランザクションのロールバック 『「中にエラー』と言う)

Caused by: org.postgresql.util.PSQLException: ERROR: prepared transactions are disabled 
    Suggerimento: Set max_prepared_transactions to a nonzero value. 

Caused by: org.postgresql.util.PSQLException: ERROR: prepared transactions are disabled 
    Suggerimento: Set max_prepared_transactions to a nonzero value. 

ERROR XAResourceTransaction - XA resource 'first': prepare for XID '3139322E3136382E322E322E746D313438373639323737373736333030303032:3139322E3136382E322E322E746D33' raised -3: the XA resource detected an internal error 
org.postgresql.xa.PGXAException: Error in preparing transaction 

だから、それが準備された必要と思われます

答えて

0

postgresql.confファイルを編集し、max_prepared_transactionsを見つけてそれをコメント解除する必要があります(#を削除してください)。線の始まり)、合理的な値を設定してください。 参照:https://www.postgresql.org/docs/9.4/static/runtime-config-resource.html

+0

私は準備されたトランザクションを有効にする方法を知っていますが、必ず有効にしていますか?そして、それが彼らなしでなぜ働くのですか? – zuno

関連する問題