Hibernate Spring @Transaction不起作用

时间:2015-03-26 17:23:29

标签: java spring hibernate transactions

我有以下内容:

@Service
public class AsyncMarketService {

    @Inject
    IdentifierManager identifierManager;

    @Transactional
    public void getProducts() {
        identifierManager.getTitleForIdentifier();
      }
}

正在从@Async方法调用服务方法。

我在日志中看到正在打开交易:

134331 DEBUG [Company-1] org.springframework.beans.factory.support.DefaultListableBeanFactory - Returning cached instance of singleton bean 'transactionManager'
134342 DEBUG [Company-1] org.springframework.orm.hibernate4.HibernateTransactionManager - Creating new transaction with name [com.estartup.caller.AsyncMarketService.getProducts]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT; ''
134343 DEBUG [Company-1] org.springframework.orm.hibernate4.HibernateTransactionManager - Opened new Session [SessionImpl(PersistenceContext[entityKeys=[],collectionKeys=[]];ActionQueue[insertions=org.hibernate.engine.spi.ExecutableList@b9b0793 updates=org.hibernate.engine.spi.ExecutableList@ee6c9e deletions=org.hibernate.engine.spi.ExecutableList@4230dd40 orphanRemovals=org.hibernate.engine.spi.ExecutableList@5d5e00b collectionCreations=org.hibernate.engine.spi.ExecutableList@56a1c8bd collectionRemovals=org.hibernate.engine.spi.ExecutableList@25d8d46b collectionUpdates=org.hibernate.engine.spi.ExecutableList@61c6c74d collectionQueuedOps=org.hibernate.engine.spi.ExecutableList@4b39a6c6 unresolvedInsertDependencies=UnresolvedEntityInsertActions[]])] for Hibernate transaction
134346 DEBUG [Company-1] org.springframework.orm.hibernate4.HibernateTransactionManager - Preparing JDBC Connection of Hibernate Session [SessionImpl(PersistenceContext[entityKeys=[],collectionKeys=[]];ActionQueue[insertions=org.hibernate.engine.spi.ExecutableList@b9b0793 updates=org.hibernate.engine.spi.ExecutableList@ee6c9e deletions=org.hibernate.engine.spi.ExecutableList@4230dd40 orphanRemovals=org.hibernate.engine.spi.ExecutableList@5d5e00b collectionCreations=org.hibernate.engine.spi.ExecutableList@56a1c8bd collectionRemovals=org.hibernate.engine.spi.ExecutableList@25d8d46b collectionUpdates=org.hibernate.engine.spi.ExecutableList@61c6c74d collectionQueuedOps=org.hibernate.engine.spi.ExecutableList@4b39a6c6 unresolvedInsertDependencies=UnresolvedEntityInsertActions[]])]
134346 DEBUG [Company-1] org.springframework.jdbc.datasource.DriverManagerDataSource - Creating new JDBC DriverManager Connection to [jdbc:mysql://localhost:3306/Company?zeroDateTimeBehavior=convertToNull]
134377 DEBUG [Company-1] org.springframework.orm.hibernate4.HibernateTransactionManager - Exposing Hibernate transaction as JDBC transaction [com.mysql.jdbc.JDBC4Connection@4d9068ae]

但是,我仍然收到错误:

Caused by: java.util.concurrent.ExecutionException: org.hibernate.HibernateException: get is not valid without active transaction
at java.util.concurrent.FutureTask.report(FutureTask.java:122)
at java.util.concurrent.FutureTask.get(FutureTask.java:192)

当我尝试从该方法(identifierManager.getTitleForIdentifier();)调用DAO以通过id检索内容时。

有什么问题?

EDITED

配置Bean:

@Configuration
@ComponentScan({ "com.estartup" })
@PropertySource("classpath:jdbc.properties")
@EnableScheduling
@EnableTransactionManagement
public class PersistenceConfig {

    @Autowired
    Environment env;

    @Bean
    public DataSource dataSource() {
        DriverManagerDataSource driverManagerDataSource = new DriverManagerDataSource(env.getProperty("connection.url"), env.getProperty("connection.username"),
                env.getProperty("connection.password"));
        driverManagerDataSource.setDriverClassName("com.mysql.jdbc.Driver");
        return driverManagerDataSource;
    }

    public PersistenceConfig() {
        super();
    }

    @Bean
    public LocalSessionFactoryBean sessionFactory() {
        LocalSessionFactoryBean factoryBean = null;
        try {
            factoryBean = createBaseSessionFactory();
            factoryBean.getHibernateProperties().setProperty("hibernate.current_session_context_class", "thread");
        } catch (Exception e) {
            e.printStackTrace();
        }
        return factoryBean;
    }

    private LocalSessionFactoryBean createBaseSessionFactory() throws IOException {
        LocalSessionFactoryBean factoryBean = new LocalSessionFactoryBean();
        Properties pp = new Properties();
        pp.setProperty("hibernate.dialect", "org.hibernate.dialect.MySQLDialect");
        pp.setProperty("hibernate.max_fetch_depth", "3");
        pp.setProperty("hibernate.current_session_context_class", "org.springframework.orm.hibernate4.SpringSessionContext");
        factoryBean.setDataSource(dataSource());
        factoryBean.setPackagesToScan(new String[] { "com.estartup.*" });
        factoryBean.setHibernateProperties(pp);
        return factoryBean;
    }

    @Bean
    @Autowired
    public HibernateTransactionManager transactionManager(SessionFactory sessionFactory) {
        HibernateTransactionManager txManager = new HibernateTransactionManager();
        txManager.setSessionFactory(sessionFactory);
        return txManager;
    }
}

2 个答案:

答案 0 :(得分:1)

您可以尝试的一件事是删除@Transactional注释并自己手动打开会话(不确定是否有更好的方法......)

@Service
public class AsyncMarketService {

    @Inject
    IdentifierManager identifierManager;

    @Inject
    SessionFactory sessionFactory;

    public void getProducts() {
        Session session = sessionFactory.openSession();
        Transaction tx = null;

        try {
            identifierManager.getTitleForIdentifier();
        } catch(Exception e) {
            if(tx != null) tx.rollback();
        } finally {
            session.close();
        }
    }
}

如果您发现自己不止一次这样做,可能会编写另一个具有闭包或其他方法的组件。

如果我在接下来的几分钟内找到更优雅的方式,我会告诉你。

答案 1 :(得分:0)

尝试将@Transactional移动到调用异步方法。事务不会通过调用层次结构从一个Spring组件传播到另一个组件,因为异步方法正在由任务执行程序稍后调度和执行。