簡體   English   中英

Hibernate Entity Manager無法在事務中注冊數據源

[英]Hibernate Entity Manager is unable to enlist datasosurce in transaction

我正在使用休眠HPA在Spring WebMVC UI后面構建應用程序。 難題的每個部分都通過了單元測試,但是我很難將應用程序粘合在一起。

似乎Hibernate事務策略正在阻止Hibernate參與事務。

到目前為止的研究: Hibernate具有默認配置的jta事務策略。 假設是

服務層上的@Transactional批注正在執行(我可以在日志中看到它)。 正在從事務管理器中檢索JDBC數據源。 然后,當事務管理器嘗試將JDBC數據源附加到事務時,它突然找不到事務。 我已經找到了代碼,當Bitronix尋找它時,事務根本就不存在。

此問題的堆棧是:

  • Postgresql XA驅動程序
  • Bitronics 2.1.7
  • 休眠4.3.7
  • 春季4.1.6
  • Pivotal tc運行時3.0.2.RELEASE / 8.0.15.A.RELEASE

這是失敗方法的代碼:

@Service
public class ConfigPropertiesServiceImpl {
    private Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    private ConfigPropertiesSDO configPropertiesSDO;

    @Autowired
    private ConfigPropertiesDAO configPropertiesDAO;

    @Transactional
    public PropertyValue fetchPropertyValue (String key)
    {
        return configPropertiesSDO.fetchProperty(key);
    }

}

顯示事務已開始的日志:

DEBUG DispatcherServlet - DispatcherServlet with name 'dispatcher' processing GET request for [/myapp-war/ajax/cfgFind]
DEBUG RequestMappingHandlerMapping - Looking up handler method for path /ajax/cfgFind
DEBUG RequestMappingHandlerMapping - Returning handler method [public org.springframework.web.servlet.ModelAndView com.myApp.ui.security.controller.ConfigurationLayoutController.getCfgFind()]
DEBUG DefaultListableBeanFactory - Returning cached instance of singleton bean 'configurationLayoutController'
DEBUG DispatcherServlet - Last-Modified value for [/myapp-war/ajax/cfgFind] is: -1
DEBUG JtaTransactionManager - Creating new transaction with name [com.myApp.svc.config.ConfigPropertiesServiceImpl.fetchPropertyValue]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT; ''
DEBUG BitronixTransactionManager - beginning a new transaction
DEBUG BitronixTransactionManager - dumping 0 transaction context(s)
DEBUG BitronixTransaction - creating new transaction with GTRID [3139322E3136382E302E35300000000005692D6D00000002]
DEBUG BitronixTransactionManager - creating new thread context
DEBUG BitronixTransactionManager - changing current thread context to a ThreadContext with transaction null, default timeout 60s
DEBUG ThreadContext - assigning <a Bitronix Transaction with GTRID [3139322E3136382E302E35300000000005692D6D00000002], status=NO_TRANSACTION, 0 resource(s) enlisted (started null)> to <a ThreadContext with transaction null, default timeout 60s>
DEBUG BitronixTransaction - changing transaction status to ACTIVE
DEBUG TransactionLogAppender - between 14848 and 14909, writing a Bitronix TransactionLogRecord with status=ACTIVE, recordLength=53, headerLength=28, time=90778990, sequenceNumber=4, crc32=-880986447, gtrid=3139322E3136382E302E35300000000005692D6D00000002, uniqueNames=
DEBUG TransactionLogAppender - disk journal appender now at position 14909
DEBUG BitronixTransaction - transaction status is changing from NO_TRANSACTION to ACTIVE - executing 0 listener(s)
DEBUG TaskScheduler - scheduling transaction timeout task on a Bitronix Transaction with GTRID [3139322E3136382E302E35300000000005692D6D00000002], status=ACTIVE, 0 resource(s) enlisted (started Thu Jan 01 19:12:58 CST 1970) for Thu Jan 01 19:13:58 CST 1970
DEBUG TaskScheduler - removing task by a Bitronix Transaction with GTRID [3139322E3136382E302E35300000000005692D6D00000002], status=ACTIVE, 0 resource(s) enlisted (started Thu Jan 01 19:12:58 CST 1970)
DEBUG TaskScheduler - scheduled a TransactionTimeoutTask on a Bitronix Transaction with GTRID [3139322E3136382E302E35300000000005692D6D00000002], status=ACTIVE, 0 resource(s) enlisted (started Thu Jan 01 19:12:58 CST 1970) scheduled for Thu Jan 01 19:13:58 CST 1970, total task(s) queued: 3
DEBUG BitronixTransactionManager - begun new transaction at Thu Jan 01 19:12:58 CST 1970

顯示該語句無法加入事務的日志:

DEBUG EntityManagerFactoryUtils - Opening JPA EntityManager
TRACE SessionFactoryImpl$SessionBuilderImpl - Opening Hibernate Session.  tenant=null, owner=org.hibernate.jpa.internal.EntityManagerImpl@7b6bfb1d
TRACE SessionImpl - Opened session at timestamp: 14400807842
DEBUG TransactionCoordinatorImpl - Skipping JTA sync registration due to auto join checking
TRACE TransactionCoordinatorImpl - registered JTA platform says we cannot currently register synchronization; skipping
DEBUG AbstractEntityManagerImpl - Looking for a JTA transaction to join
DEBUG AbstractEntityManagerImpl - Unable to join JTA transaction
DEBUG TransactionCoordinatorImpl - Skipping JTA sync registration due to auto join checking

這是我的Spring Context初始化:

public class AppInitializer implements WebApplicationInitializer {

    @Override
    public void onStartup(ServletContext container) throws ServletException {
        Logger logger = LoggerFactory.getLogger(this.getClass());


        AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext();
        rootContext.register(DatabaseConfig.class);
        rootContext.refresh();

        // Manage the lifecycle of the root appcontext
        container.addListener(new ContextLoaderListener(rootContext));
        container.setInitParameter("defaultHtmlEscape", "true");

        AnnotationConfigWebApplicationContext mvcContext = new AnnotationConfigWebApplicationContext();
        mvcContext.register(ViewConfig.class);
        mvcContext.setServletContext(container);

        ServletRegistration.Dynamic servlet = container.addServlet(
                "dispatcher", new DispatcherServlet(mvcContext));

        servlet.setLoadOnStartup(1);
        Set<String> mappingConflicts = servlet.addMapping("/");

        if (!mappingConflicts.isEmpty()) {
            for (String s : mappingConflicts) {
                logger.error("Mapping conflict: " + s);
            }
            throw new IllegalStateException(
                    "'appServlet' cannot be mapped to '/' under Tomcat versions <= 7.0.14");
        }
    }
}

...以及配置了交易的數據庫配置類...

@EnableTransactionManagement
@ComponentScan({ "com.myApp.svc.*","com.myApp.core.*","com.myApp.ui.*" })
@Configuration
public class DatabaseConfig {


    @Bean(destroyMethod="shutdown")
    public BitronixTransactionManager bitronixTransactionManager() {
        btmConfig();

        return new BitronixTransactionManager();
    }


    @Bean
    public JtaTransactionManager transactionManager() {
        JtaTransactionManager mgr = new JtaTransactionManager();

        mgr.setTransactionManager(bitronixTransactionManager ());
        mgr.setUserTransaction(bitronixTransactionManager ());

        mgr.afterPropertiesSet();

        return mgr;
    }

    @Bean
    public TransactionTemplate transactionTemplate ()
    {
        return new TransactionTemplate (transactionManager());
    }

    @Bean(initMethod = "init", destroyMethod = "close")
    public DataSource dataSource() {

        PoolingDataSource dataSourceInstance = new PoolingDataSource();
        dataSourceInstance.set ... ();

        dataSourceInstance.init();

        return dataSourceInstance;
    }

    @Bean
public LocalContainerEntityManagerFactoryBean localContainerEntityManagerFactoryBean()
        throws IOException {
    // The bean isn't created yet, but we need some of its functions
    // This instance will be released as soon as the method goes out of
    // scope
    BitronixTransactionManager tm = bitronixTransactionManager();


    PrivateDatastoreServiceImpl pds = new PrivateDatastoreServiceImpl();
    pds.setPrivateDatastorePropertiesFile(privateDatastorePropertiesFile());
    pds.init();

    LocalContainerEntityManagerFactoryBean emf = null;

    PrivateDatastoreConfigurationModel model = pds
            .retrieveRawJdbcParameters();

    Properties props = new Properties();
    props.setProperty(HIBERNATE_DIALECT,
            pds.getHibernateStrategy(model.getDbType()));
    props.setProperty(HIBERNATE_DDL_AUTO, "false");
    props.setProperty(HIBERNATE_SHOW_SQL, "false");
    props.setProperty(HIBERNATE_FORMAT_SQL, "false");
    props.setProperty("hibernate.current_session_context_class", 
            "jta");
    props.setProperty("hibernate.transaction.jta.platform",
            org.hibernate.engine.transaction.jta.platform.internal.BitronixJtaPlatform.class.getName());
    props.setProperty("hibernate.jndi.class", 
            bitronix.tm.jndi.BitronixInitialContextFactory.class.getName());
    props.setProperty("jta.UserTransaction", 
            "BTMUserTransaction");

    emf = new LocalContainerEntityManagerFactoryBean();
    emf.setJtaDataSource(securityDataSource());
    emf.setJpaVendorAdapter(jpaVendorAdapter());
    emf.setPersistenceUnitName("myAppPersistence");
    emf.setPackagesToScan("com.myApp.*");
    emf.setJpaProperties(props);

    return emf;
}


}

編輯:添加了軟件堆棧的詳細信息

存在多個相互作用的問題,所有這些問題都導致休眠狀態拒絕加入事務。

  1. 休眠屬性不太正確。 如上所述,休眠甚至沒有嘗試加入事務。 最終的休眠配置為:

     Properties props = new Properties(); props.setProperty(HIBERNATE_DIALECT, pds.getHibernateStrategy(model.getDbType())); props.setProperty(HIBERNATE_DDL_AUTO, "false"); props.setProperty(HIBERNATE_SHOW_SQL, "false"); props.setProperty(HIBERNATE_FORMAT_SQL, "false"); props.setProperty("hibernate.transaction.jta.platform", org.hibernate.engine.transaction.jta.platform.internal.BitronixJtaPlatform.class.getName()); props.setProperty("hibernate.jndi.class", bitronix.tm.jndi.BitronixInitialContextFactory.class.getName()); props.setProperty("jta.UserTransaction", "BTMUserTransaction"); props.setProperty("jdbc.exclusive-connection.mode", "Transactional"); // JTA stuff props.setProperty("hibernate.connection.release_mode","after_statement"); props.setProperty("hibernate.current_session_context_class","jta"); props.setProperty("hibernate.transaction.manager_lookup_class","org.hibernate.transaction.BTMTransactionManagerLookup"); 
  2. bitronix事務管理器必須是單例。 在構建新的事務管理器的過程中,bean應該定義為:

     @Bean(destroyMethod="shutdown") public BitronixTransactionManager bitronixTransactionManager() { btmConfig(); return TransactionManagerServices.getTransactionManager(); } 

有兩名交易經理在附近徘徊,使這個問題感到困惑。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM