在 spring 中有条件地配置 transactionManager 时如何使用 Transactional 注释?
How to use Transactional annotation when config transactionManager conditionally in spring?
我在 spring 项目中使用多个数据源。
我 enable/disable 在项目启动时通过手动配置它们。
一次所有这些都可能处于活动状态
因此 transactionManager bean 可能处于活动状态或不处于活动状态。
我在spring配置class中通过@Conditional注解实现。
当我在方法上使用禁用事务注释时,我有 NoSuchBeanDefinitionException。
当我有条件地定义 transactionManager bean 时如何在方法上使用事务性注释?
archiveTransactionManager bean 不是由 @Conditional 注释创建的,我希望spring跳过检查条件事务管理器的 bean 验证。
对于条件 sessionFactory bean,我将 Autowired 注释中的 'required' 参数设置为 false 以防止 spring 抛出 NoSuchBeanDefinitionException 但我为 @Transactional 做了什么?
配置class
@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!
我希望spring在某些情况下跳过条件事务管理器 bean 的 bean 验证,这些情况它们不是由条件创建的 .
您使用了错误的注解来命名 bean。 @Qualifier
用于注入点指定名称。您需要使用 @Bean
为 bean 命名。所以你的 bean 定义需要像这样:
@Bean("archiveTransactionManager")
@Conditional(ArchiveCondition.class)
public HibernateTransactionManager archiveTransactionManager() {
HibernateTransactionManager transactionManager = new HibernateTransactionManager();
transactionManager.setSessionFactory(archiveSessionFactory());
return transactionManager;
}
我会将其视为后备方案,您必须在失败后恢复。在这种情况下,有一个用
注释的方法调用方法
@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() {
}
请记住,您必须同时声明它们。
我实现了一个 no-op SessionFactory 并在 spring 配置 class 中实例化它,每当 archive_mode 被禁用时:
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");
}
...
}
我在 spring 项目中使用多个数据源。 我 enable/disable 在项目启动时通过手动配置它们。 一次所有这些都可能处于活动状态 因此 transactionManager bean 可能处于活动状态或不处于活动状态。
我在spring配置class中通过@Conditional注解实现。 当我在方法上使用禁用事务注释时,我有 NoSuchBeanDefinitionException。
当我有条件地定义 transactionManager bean 时如何在方法上使用事务性注释?
archiveTransactionManager bean 不是由 @Conditional 注释创建的,我希望spring跳过检查条件事务管理器的 bean 验证。
对于条件 sessionFactory bean,我将 Autowired 注释中的 'required' 参数设置为 false 以防止 spring 抛出 NoSuchBeanDefinitionException 但我为 @Transactional 做了什么?
配置class
@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!
我希望spring在某些情况下跳过条件事务管理器 bean 的 bean 验证,这些情况它们不是由条件创建的 .
您使用了错误的注解来命名 bean。 @Qualifier
用于注入点指定名称。您需要使用 @Bean
为 bean 命名。所以你的 bean 定义需要像这样:
@Bean("archiveTransactionManager")
@Conditional(ArchiveCondition.class)
public HibernateTransactionManager archiveTransactionManager() {
HibernateTransactionManager transactionManager = new HibernateTransactionManager();
transactionManager.setSessionFactory(archiveSessionFactory());
return transactionManager;
}
我会将其视为后备方案,您必须在失败后恢复。在这种情况下,有一个用
注释的方法调用方法@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() {
}
请记住,您必须同时声明它们。
我实现了一个 no-op SessionFactory 并在 spring 配置 class 中实例化它,每当 archive_mode 被禁用时:
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");
}
...
}