在春季有条件地配置transactionManager时如何使用事务注释?

时间:2019-06-12 07:16:47

标签: spring hibernate configuration spring-data spring-transactions

我在spring项目中使用了多个数据源。 我在项目启动时通过手动配置启用/禁用它们。 一次所有的人都可能处于活动状态 因此,transactionManager bean可能处于活动状态或不处于活动状态。

我在Spring配置类中通过@Conditional注释实现了它。 当我在方法上使用禁用事务注释时,会出现NoSuchBeanDefinitionException。

当我有条件地定义transactionManager bean时,如何在方法上使用事务注释?

archiveTransactionManager bean不是通过@Conditional注释创建的,我希望Spring跳过检查条件事务管理器的bean验证。

对于条件sessionFactory bean,我将Autowired注释中的“ required”参数设置为false,以防止spring抛出NoSuchBeanDefinitionException,但是我该如何对@Transactional进行操作?

配置类

    @Bean("archiveTransactionManager")
    @Conditional(ArchiveCondition.class)
    public HibernateTransactionManager archiveTransactionManager() {
        HibernateTransactionManager transactionManager = new HibernateTransactionManager();
        transactionManager.setSessionFactory(archiveSessionFactory());
        return transactionManager;
    }

交易方法

    @Transactional(value = "archiveTransactionManager", readOnly = true)
    private List<DocumentItem> loadArchivedDocumentItem() {...}

用法

if(GeneralSetting.isArchive)
   documentService.loadArchivedDocumentItem();

当前结果:

org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'archiveTransactionManager' available: No matching PlatformTransactionManager bean found for qualifier 'archiveTransactionManager' - neither qualifier match nor bean name match!

在某些不是由条件创建的情况下,我希望有条件transactionManager bean的春季跳过bean验证

3 个答案:

答案 0 :(得分:2)

无论何时禁用archive_mode,我都会实现一个无操作SessionFactory并在spring配置类中实例化它:

SpringConfig.java

    @Bean("archiveSessionFactory")
    public SessionFactory archiveSessionFactory() {
        return ServerConf.ARCHIVE_MODE ? createNormalSessionFactory() : new DummySessionFactory();
    }

    @Bean("archiveTransactionManager")
    public HibernateTransactionManager archiveTransactionManager() {
        HibernateTransactionManager transactionManager = new HibernateTransactionManager();
        transactionManager.setSessionFactory(archiveSessionFactory());
        return transactionManager;
    }

DummySessionFactory.java

public class DummySessionFactory implements SessionFactory {
...
    // These two methods call in spring initializing and we have to implement them
    @Override
    public Metamodel getMetamodel() {
       return new MetamodelImpl(null);
    }

    @Override
    public Map<String, Object> getProperties() {
       return null;
    }

    //Throw suitable exception in other methods
    @Override
    public Session getCurrentSession() throws HibernateException {
        throw new HibernateException("Desired mode is Disabled");
    }
...
}

答案 1 :(得分:0)

我会将其视为后备情况,在这种情况下您必须在失败后恢复。在这种情况下,请使用

注释方法调用方法

@Transactional(value = "archiveTransactionManager", readOnly = true)

在失败(或异常)的情况下,调用方法带有

@Transactional(value = "alternativeTransactionManager", readOnly = true)

public void doSomething() {
    try {
        tryFirst();
    } catch (Exception e) {
        tryAlternative();
    }
}

@Transactional(value = "archiveTransactionManager", readOnly = true)
public void tryFirst() {

}

@Transactional(value = "alternativeTransactionManager", readOnly = true)
public void tryAlternative() {

}

请记住,您必须同时声明它们。

答案 2 :(得分:-1)

您使用了错误的注释来命名bean。在注入点上使用@Qualifier来指定名称。您需要使用@Bean为bean命名。因此,您的bean定义需要如下所示:

@Bean("archiveTransactionManager")
@Conditional(ArchiveCondition.class)
public HibernateTransactionManager archiveTransactionManager() {
  HibernateTransactionManager transactionManager = new HibernateTransactionManager();
  transactionManager.setSessionFactory(archiveSessionFactory());
  return transactionManager;
}