当前位置: 首页 > 知识库问答 >
问题:

Spring代理不处理@Transactional[重复]

养翔
2023-03-14

河楼

我试图配置Hibernate本地开发与HSQL数据库,但我被困在Spring不处理事务。

配置数据源,会话工厂等...

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

...

调用人员Dao.saveOrUpdate()后打印的堆栈跟踪

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\u session\u context\u具有值的类(托管,线程)
  • 以及其他许多小的配置更改

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

共有1个答案

史骏
2023-03-14

您不能在@PostConstruct中使用@Transactional。请参阅@PostConstruct方法上的@Transactional

 类似资料:
  • 我正在使用spring批处理使用RepositoryItemReader从postgresql DB读取记录,然后将其写入主题。我看到大约有100万条记录需要处理,但它并没有处理所有的记录。我已经将reader的pageSize设置为10,000并且与提交间隔(块大小)相同

  • 我在表中总共有8条记录,其中6条在spring批处理调用read时可以使用jpareader。现在我将页面大小和块大小设置为1以进行测试。期望作业运行时,它应该进行6次读取调用,然后它应该逐个处理,逐个写入。但实际上发生的是,它只是调用read 4次(从日志中我可以看到这样读取页面0...1)并处理4个,其中一个由于不匹配写入标准而被过滤掉,然后它只是更新了3个记录,作业标记为成功完成。

  • 如何将批次大小I.t.o设置为要批次的重量?我目前正在模拟一种马铃薯植物。由于土豆的随机性,土豆(代理)都有自己的重量,但现在我必须将它们分装成10公斤的袋子。重量应该在10kg以上,但不能更小,所以它将是9.9kg加上一个土豆。 F1帮助功能建议使用自定义队列。但我不知道如何继续这一选择。 任何帮助都将不胜感激

  • 当我使用Spring批处理管理运行长时间运行的批处理作业的多个实例时,它会在达到jobLauncher线程池任务执行程序池大小后阻止其他作业运行。但是从cron中提取多个工作似乎效果不错。下面是作业启动器配置。 Spring批处理管理员Restful API是否使用不同于xml配置中指定的作业启动器?

  • 我对Spring批处理跳过逻辑有一些问题。我已经配置了一个作业的步骤来跳过两个异常(SQLIntegrityConstraintViolation异常和乐观锁定失败异常): 但当作业运行时,由于我将其配置为跳过的异常,作业以未知状态完成: 我做错什么了吗?我希望这一步跳过负责抛出其中一个异常的项,并继续处理,以便以完成状态结束。