Spring代理不处理@Transactional

时间:2016-04-20 14:37:13

标签: java spring hibernate transactional sessionfactory

希罗

我尝试使用HSQL数据库配置Hibernate进行本地开发,但我仍然坚持Spring不处理事务。

配置数据源,sessionFactory等......

package com.globesy.hcp.context.config;

import java.io.IOException;
import java.util.Properties;

import javax.sql.DataSource;

import org.hibernate.SessionFactory;
import org.hibernate.boot.registry.StandardServiceRegistry;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;
import org.springframework.core.env.Environment;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.orm.hibernate4.LocalSessionFactoryBuilder;
import org.springframework.orm.hibernate5.HibernateTransactionManager;
import org.springframework.transaction.interceptor.TransactionInterceptor;

import com.globesy.hcp.context.config.constants.BeanConstants;
import com.globesy.hcp.context.config.constants.PropertyConstants;

@Configuration
public class DataSourceConfig {

    private static final Logger LOGGER = LoggerFactory.getLogger(DataSourceConfig.class);

    @Autowired
    private Environment environment;

    @Bean(name=BeanConstants.SESSION_FACTORY_BEAN_NAME)
    @DependsOn(BeanConstants.DATASOURCE_BEAN_NAME)
    public SessionFactory sessionFactory(@Qualifier(BeanConstants.DATASOURCE_BEAN_NAME) DataSource dataSource) throws IOException {
        org.hibernate.cfg.Configuration hibernateConfig = new org.hibernate.cfg.Configuration()
                .addProperties(hibernateProperties());

        StandardServiceRegistry registry = new StandardServiceRegistryBuilder().applySettings(hibernateConfig.getProperties()).build();

        return new LocalSessionFactoryBuilder(dataSource)
                .scanPackages(PropertyConstants.HIBERNATE_PACKAGES_TO_SCAN)
                .setProperties(hibernateConfig.getProperties())
                .buildSessionFactory(registry);
     }

    @Bean(name=BeanConstants.DATASOURCE_BEAN_NAME)
    public DataSource dataSource(){

        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setDriverClassName(environment.getRequiredProperty(PropertyConstants.HIBERNATE_DRIVER_CLASS_NAME));
        dataSource.setUrl(environment.getRequiredProperty(PropertyConstants.HIBERNATE_URL));
        dataSource.setUsername(environment.getRequiredProperty(PropertyConstants.HIBERNATE_USERNAME));
        dataSource.setPassword(environment.getRequiredProperty(PropertyConstants.HIBERNATE_PASSWORD));

        LOGGER.info("DataSource initialized");
        return dataSource;
    }

    @Bean(name=BeanConstants.TRANSACTION_MANAGER)
    @DependsOn({BeanConstants.SESSION_FACTORY_BEAN_NAME,BeanConstants.DATASOURCE_BEAN_NAME})
    public HibernateTransactionManager transactionManager(@Qualifier(BeanConstants.SESSION_FACTORY_BEAN_NAME) SessionFactory sessionFactory,
                                                          @Qualifier(BeanConstants.DATASOURCE_BEAN_NAME) DataSource source) {

        HibernateTransactionManager manager = new HibernateTransactionManager(); 

        manager.setDataSource(source);
        manager.setSessionFactory(sessionFactory);
        manager.setEntityInterceptorBeanName(BeanConstants.TRANSACTION_INTERCEPTOR);
        manager.setRollbackOnCommitFailure(true);
        manager.afterPropertiesSet();

        LOGGER.info("HibernateTransactionManager initialized");
        return manager;
    }

    @Bean(name=BeanConstants.TRANSACTION_INTERCEPTOR)
    public TransactionInterceptor transactionInterceptor(){

        Properties props = new Properties();
        props.put("save", "PROPAGATION_REQUIRED");

        TransactionInterceptor interceptor = new TransactionInterceptor();
        interceptor.setTransactionAttributes(props);

        return interceptor;
    }

    private Properties hibernateProperties() {
            Properties properties = new Properties();
            properties.put(PropertyConstants.HIBERNATE_DIALECT, environment.getRequiredProperty(PropertyConstants.HIBERNATE_DIALECT));
            properties.put(PropertyConstants.HIBERNATE_DRIVER_CLASS_NAME, environment.getRequiredProperty(PropertyConstants.HIBERNATE_DRIVER_CLASS_NAME));
            properties.put(PropertyConstants.HIBERNATE_SHOW_SQL, environment.getRequiredProperty(PropertyConstants.HIBERNATE_SHOW_SQL));
            properties.put(PropertyConstants.HIBERNATE_URL, environment.getRequiredProperty(PropertyConstants.HIBERNATE_URL));
            properties.put(PropertyConstants.HIBERNATE_USERNAME, environment.getRequiredProperty(PropertyConstants.HIBERNATE_USERNAME));
            properties.put(PropertyConstants.HIBERNATE_PASSWORD, environment.getRequiredProperty(PropertyConstants.HIBERNATE_PASSWORD));
            properties.put(PropertyConstants.HIBERNATE_HBM2DLL_AUTO, environment.getRequiredProperty(PropertyConstants.HIBERNATE_HBM2DLL_AUTO));
            properties.put(PropertyConstants.HIBERNATE_DEFAULT_SCHEMA, environment.getRequiredProperty(PropertyConstants.HIBERNATE_DEFAULT_SCHEMA));

            return properties;        
    }
}

具有针对本地环境的hibernate配置的属性文件

#hibernate config
hibernate.connection.driverClassName=org.hsqldb.jdbcDriver
hibernate.connection.url=jdbc:hsqldb:hsql://localhost:9001/hcp_demo
hibernate.default_schema=public
hibernate.connection.username=sa
hibernate.connection.password=
hibernate.dialect=org.hibernate.dialect.HSQLDialect
hibernate.show_sql=true
hibernate.hbm2dll.auto=update

抛出异常的代码的调用点

@RestController
public class VerifyController {

    @Autowired
    private PersonDao personDao;

    private static final Logger LOGGER = LoggerFactory.getLogger(VerifyController.class);

    @PostConstruct
    @Transactional
    public void init(){
        Person person = new Person();

        person.setFirstName("Jozef");
        person.setSurname("Novak");

        personDao.saveOrUpdate(person);
    }

...

调用 personDao.saveOrUpdate()后打印Stacktrace

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'verifyController': Invocation of init method failed; nested exception is org.hibernate.HibernateException: No CurrentSessionContext configured!
    at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor.postProcessBeforeInitialization(InitDestroyAnnotationBeanPostProcessor.java:136)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInitialization(AbstractAutowireCapableBeanFactory.java:408)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1570)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:545)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:772)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:839)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:538)
    at org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:444)
    at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:326)
    at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:107)
    at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:5066)
    at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5584)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:147)
    at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1572)
    at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1562)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)
Caused by: org.hibernate.HibernateException: No CurrentSessionContext configured!
    at org.hibernate.internal.SessionFactoryImpl.getCurrentSession(SessionFactoryImpl.java:685)
    at com.globesy.hcp.dao.AbstractDao.getSession(AbstractDao.java:13)
    at com.globesy.hcp.dao.AbstractDao.saveOrUpdate(AbstractDao.java:25)
    at com.globesy.hcp.controller.VerifyController.init(VerifyController.java:34)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:497)
    at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleElement.invoke(InitDestroyAnnotationBeanPostProcessor.java:354)
    at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleMetadata.invokeInitMethods(InitDestroyAnnotationBeanPostProcessor.java:305)
    at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor.postProcessBeforeInitialization(InitDestroyAnnotationBeanPostProcessor.java:133)
    ... 23 more

我已经尝试了什么

  • 在HibernateTransactionManager / DatasourceTransactionManager
  • 之间切换
  • 属性 - hibernate.current_session_context_class 包含值(托管,线程)
  • 以及许多其他小配置更改

我希望你们知道这个配置可能出现什么问题,因为我和谷歌都没有。

1 个答案:

答案 0 :(得分:0)

您无法在@Transactional中使用@PostConstruct。见@Transactional on @PostConstruct method