我正在Spring Boot中开发一个需要连接到两个不同数据库的应用程序。为此,我必须手动配置连接。 最初一切似乎都正常,但后来我意识到我在交易方面遇到了问题。 实际上,尽管我在方法上使用了事务性注释,但我意识到我在数据库上写的每条记录都会立即提交,并且如果引发异常,则不会发生回滚。 似乎交易没有进行。
这是我对第一个数据库的实际配置。
import java.util.HashMap;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.orm.jpa.hibernate.SpringImplicitNamingStrategy;
import org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.env.Environment;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.jdbc.datasource.lookup.JndiDataSourceLookup;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.transaction.jta.JtaTransactionManager;
@Configuration
@EnableConfigurationProperties
@EnableJpaRepositories(
entityManagerFactoryRef = "fooEntityManager",
basePackages = "xx.yy.zz.repository"
)
@EnableTransactionManagement
public class FooConfig {
@Autowired
private Environment env;
@Value("${spring.datasource.primary.jndi-name}")
private String jndiConnection;
@Primary
@Bean(destroyMethod = "")
public DataSource ds() {
JndiDataSourceLookup lookup = new JndiDataSourceLookup();
return lookup.getDataSource(jndiConnection);
}
@Bean
@Primary
public LocalContainerEntityManagerFactoryBean fooEntityManager(DataSource ds) {
LocalContainerEntityManagerFactoryBean em
= new LocalContainerEntityManagerFactoryBean();
em.setDataSource(ds());
em.setPackagesToScan(
new String[] { "xx.yy.zz.entity" });
HibernateJpaVendorAdapter vendorAdapter
= new HibernateJpaVendorAdapter();
vendorAdapter.setShowSql(true);
em.setJpaVendorAdapter(vendorAdapter);
HashMap<String, Object> properties = new HashMap<>();
properties.put("hibernate.hbm2ddl.auto", "none");
properties.put("hibernate.dialect",
env.getProperty("spring.jpa.properties.hibernate.dialect"));
properties.put("hibernate.physical_naming_strategy", SpringPhysicalNamingStrategy.class.getName());
properties.put("hibernate.implicit_naming_strategy", SpringImplicitNamingStrategy.class.getName());
em.setJpaPropertyMap(properties);
return em;
}
@Primary
@Bean(name="transactionManager")
public PlatformTransactionManager fooTransactionManager() {
JpaTransactionManager transactionManager
= new JpaTransactionManager();
transactionManager.setEntityManagerFactory(
fooEntityManager(ds()).getObject());
return transactionManager;a
}
}
我也尝试使用JTA,但是相反,这次应用程序从未在DB上编写过。 这是jta配置。
import java.util.HashMap;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.orm.jpa.hibernate.SpringImplicitNamingStrategy;
import org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.env.Environment;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.jdbc.datasource.lookup.JndiDataSourceLookup;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.transaction.jta.JtaTransactionManager;
@Configuration
@EnableConfigurationProperties
@EnableJpaRepositories(
basePackages = "xx.yy.zzzz.repository",
entityManagerFactoryRef = "fooEntityManager"
)
@EnableTransactionManagement
public class FooConfig {
@Value("${spring.datasource.primary.jndi-name}")
private String jndiConnection;
@Autowired
private Environment env;
@Primary
@Bean(destroyMethod = "")
public DataSource ds() {
JndiDataSourceLookup lookup = new JndiDataSourceLookup();
return lookup.getDataSource(jndiConnection);
}
@Bean
@Primary
public LocalContainerEntityManagerFactoryBean fooEntityManager(DataSource ds) {
LocalContainerEntityManagerFactoryBean em
= new LocalContainerEntityManagerFactoryBean();
em.setJtaDataSource(ds());
em.setPackagesToScan(
new String[] { "xx.yy.zz.entity" });
HibernateJpaVendorAdapter vendorAdapter
= new HibernateJpaVendorAdapter();
vendorAdapter.setShowSql(true);
em.setJpaVendorAdapter(vendorAdapter);
HashMap<String, Object> properties = new HashMap<>();
properties.put("hibernate.hbm2ddl.auto", "none");
properties.put("hibernate.dialect",
env.getProperty("spring.jpa.properties.hibernate.dialect"));
properties.put("hibernate.transaction.jta.platform",
env.getProperty("org.hibernate.service.jta.platform.internal.JBossAppServerJtaPlatform"));
properties.put("hibernate.physical_naming_strategy", SpringPhysicalNamingStrategy.class.getName());
properties.put("hibernate.implicit_naming_strategy", SpringImplicitNamingStrategy.class.getName());
em.setJpaPropertyMap(properties);
return em;
}
@Primary
@Bean(name="transactionManager")
public PlatformTransactionManager fooTransactionManager() {
JtaTransactionManager transactionManager = new JtaTransactionManager();
return transactionManager;
}
}
这就是所有的连接配置。
edit1: 我试图在只有一个数据库连接的应用程序中使用此配置。似乎工作正常。我写了一个事务性方法,在数据库中插入了10个元素,如果在此方法中抛出错误,则数据库中将不会插入任何内容。