- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
设置如下:
我们的应用程序数据库由两个独立的用户构建和使用:
This enables us to lock any schema changes until needed so no profound changes happen through the app user.
我正在使用包含这两个用户的实时 Oracle 数据库运行集成测试。在类本身上,我使用了 @SqlConfig(dataSource = "schemaDataSource", transactionManager = "transactionManagerSchema")
。
在测试方法中,我放置了两个失败的 @Sql
,因为在 SqlScriptsTestExecutionListener
类中,事务未管理相同的数据源。 (因此在下面进一步显示错误消息)。
我已经尝试手动将数据源设置为事务管理器,如下面的配置类所示,但是似乎每次都有一些未知进程覆盖它。 (我最好的猜测是通过 @DataJpaTest
注释,但我不知道到底是 11 Auto Configurations 中的哪一个做了它,正如你所看到的,我已经禁用了几个但没有效果)。
测试类:
@RunWith(SpringRunner.class)
@DataJpaTest(excludeAutoConfiguration = {TestDatabaseAutoConfiguration.class, DataSourceAutoConfiguration.class})
@FlywayTest
@SqlConfig(dataSource = TestDataSourceConfig.SCHEMA_DATA_SOURCE, transactionManager = "transactionManagerSchema")
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, classes = {TestDataSourceConfig.class, TestFlywayConfig.class})
@EntityScan(basePackageClasses = BaseEnum.class)
public class NotificationTypeEnumTest {
@Autowired
private EntityManager em;
@Test
@Sql(statements = {"INSERT INTO MYAPP_ENUM (ENUM_ID, \"TYPE\", \"VALUE\") VALUES (MYAPP_ENUM_ID_SEQ.nextval, '" + NotificationTypeEnum.DTYPE + "', 'foo')"}, executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD)
@Sql(statements = {"DELETE FROM MYAPP_ENUM"}, executionPhase = Sql.ExecutionPhase.AFTER_TEST_METHOD)
public void canFetchNotificationTypeEnum() throws Exception {
TypedQuery<NotificationTypeEnum> query = em.createQuery("select a from NotificationTypeEnum a", NotificationTypeEnum.class);
NotificationTypeEnum result = query.getSingleResult();
assertEquals("foo", result.getValue());
assertEquals(NotificationTypeEnum.DTYPE, result.getConfigType());
}
}
数据源和 TM 配置:
@Slf4j @Configuration @EnableTransactionManagement
public class TestDataSourceConfig {
public static final String SCHEMA_DATA_SOURCE = "schemaDataSource";
public static final String SCHEMA_TRANSACTION_MANAGER = "schemaTransactionManager";
/*Main Datasource and supporting beans*/
@Bean @Primary @ConfigurationProperties(prefix = "spring.datasource")
public DataSource dataSource() { return new DriverManagerDataSource(); }
@Bean @Primary @Autowired
public PlatformTransactionManager transactionManager(EntityManagerFactory emf) { return new JpaTransactionManager(emf); }
@Bean(name = SCHEMA_DATA_SOURCE) @ConfigurationProperties(prefix = "myapp.datasource.test_schema")
public DataSource schemaDataSource() { return new DriverManagerDataSource(); }
@Bean(name = SCHEMA_TRANSACTION_MANAGER) @Autowired
public PlatformTransactionManager transactionManagerSchema(@Qualifier(SCHEMA_DATA_SOURCE) DataSource dataSource) {
JpaTransactionManager jpaTransactionManager = new JpaTransactionManager();
jpaTransactionManager.setDataSource(dataSource);
return jpaTransactionManager;
}
}
我无法放入标题的完整错误是:
java.lang.IllegalStateException: Failed to execute SQL scripts for test context
...
SOME LONG STACK TRACE
...
the configured DataSource [org.springframework.jdbc.datasource.DriverManagerDataSource] (named 'schemaDataSource') is not the one associated with transaction manager [org.springframework.orm.jpa.JpaTransactionManager] (named 'transactionManagerSchema').
当只有一个 DataSource
时,Spring 自动配置模型似乎工作正常,但是,一旦有 2 个或更多,假设就会失效,程序员需要手动填充在所需的配置中突然出现(大量)差距。
我是否缺少对数据源和事务管理器的一些基本理解?
经过一些调试,我发现在检索 TransactionManager 以与 @Sql
脚本注释一起使用时,我创建的 bean 正在调用 afterPropertiesSet()
方法.这会导致它拥有的任何 EntityManagerFactory
(即 JpaTransactionManager.entityManagerFactory
)根据其配置的 EntityManagerFactoryInfo.getDataSource()
设置数据源。 EntityManagerFactory
本身是调用 JpaTransactionManager.setBeanFactory
方法的结果(因为它实现了 BeanFactoryAware
)。
这是 Spring 代码:
// JpaTransactionManager.java
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
if (getEntityManagerFactory() == null) {
if (!(beanFactory instanceof ListableBeanFactory)) {
throw new IllegalStateException("Cannot retrieve EntityManagerFactory by persistence unit name " +
"in a non-listable BeanFactory: " + beanFactory);
}
ListableBeanFactory lbf = (ListableBeanFactory) beanFactory;
setEntityManagerFactory(EntityManagerFactoryUtils.findEntityManagerFactory(lbf, getPersistenceUnitName()));
}
}
然后我尝试创建自己的 EntityManagerFactory bean 以尝试将其注入(inject)到我创建的事务管理器中,但这似乎打开了 Hibernate 特定类,我希望在 JPA
级别保持抽象。以及乍一看很难配置。
最佳答案
解决方案是使用提供的 spring EntityManagerFactoryBuilder
组件控制 EntityManagerFactoryBeans
的创建,并使用 @PersistenceContext
将 EntityManager 注入(inject)到测试中> 注释。
@SqlConfig(dataSource = TestDataSourceConfig.SCHEMA_DATA_SOURCE, transactionManager = SCHEMA_TRANSACTION_MANAGER, transactionMode = SqlConfig.TransactionMode.ISOLATED)
...
public class MyJUnitTest {
@PersistenceContext(unitName = "pu")
private EntityManager em;
...
@Test
@Sql(statements = {"SOME SQL USING THE PRIVILEGED SCHEMA CONNECTION"}, ...)
public void myTest() {
em.createQuery("...").getResultList() // uses the APP database user.
}
}
下面是两个数据源的配置。与应用程序相关的 DataSource bean 在其定义中都具有 @Primary
以消除任何 @Autowired
依赖项的歧义。除了通过 @DataJpaTest
类完成的自动 hibernate 配置之外,不需要 Hibernate 特定类。
@Configuration
@EnableTransactionManagement
@EnableConfigurationProperties(JpaProperties.class)
public class TestDataSourceConfig {
public static final String SCHEMA_DATA_SOURCE = "schemaDS";
public static final String SCHEMA_TRANSACTION_MANAGER = "schemaTM";
public static final String SCHEMA_EMF = "schemaEMF";
/*Main Datasource and supporting beans*/
@Bean
@Primary
@ConfigurationProperties(prefix = "spring.datasource")
public DataSource dataSource() {
return new DriverManagerDataSource();
}
@Bean @Primary @Autowired
public PlatformTransactionManager transactionManager(EntityManagerFactory emf) { return new JpaTransactionManager(emf); }
@Bean @Primary
public LocalContainerEntityManagerFactoryBean emfBean(
EntityManagerFactoryBuilder entityManagerFactoryBuilder,
DataSource datasource,
JpaProperties jpaProperties) {
return entityManagerFactoryBuilder
.dataSource(datasource)
.jta(false)
.packages(CourseOffering.class)
.persistenceUnit("pu")
.properties(jpaProperties.getProperties())
.build();
}
@Bean(name = SCHEMA_EMF)
public LocalContainerEntityManagerFactoryBean emfSchemaBean(
EntityManagerFactoryBuilder entityManagerFactoryBuilder,
@Qualifier(SCHEMA_DATA_SOURCE) DataSource schemaDataSource,
JpaProperties jpaProperties) {
return entityManagerFactoryBuilder
.dataSource(schemaDataSource)
.jta(false)
.packages(CourseOffering.class)
.persistenceUnit("spu")
.properties(jpaProperties.getProperties())
.build();
}
@Bean(name = SCHEMA_DATA_SOURCE)
@ConfigurationProperties(prefix = "myapp.datasource.test_schema")
public DataSource schemaDataSource() { return new DriverManagerDataSource(); }
@Bean(name = SCHEMA_TRANSACTION_MANAGER)
public PlatformTransactionManager transactionManagerSchema(
@Qualifier(SCHEMA_EMF) EntityManagerFactory emfSchemaBean) {
JpaTransactionManager jpaTransactionManager = new JpaTransactionManager();
jpaTransactionManager.setEntityManagerFactory(emfSchemaBean);
return jpaTransactionManager;
}
}
实际测试类:
@RunWith(SpringRunner.class) // required for all spring tests
@DataJpaTest(excludeAutoConfiguration = {TestDatabaseAutoConfiguration.class, DataSourceAutoConfiguration.class}) // this stops the default data source and database being configured.
@SqlConfig(dataSource = TestDataSourceConfig.SCHEMA_DATA_SOURCE, transactionManager = SCHEMA_TRANSACTION_MANAGER, transactionMode = SqlConfig.TransactionMode.ISOLATED) // make sure the @Sql statements are run using the SCHEMA datasource and txManager in an isolated way so as not to cause problems when running test methods requiring these statements to be run.
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, classes = {TestDataSourceConfig.class})
@TestExecutionListeners({
SqlScriptsTestExecutionListener.class, // enables the @Sql script annotations to work.
SpringBootDependencyInjectionTestExecutionListener.class, // injects spring components into the test (i.e. the EntityManager)
TransactionalTestExecutionListener.class}) // I have this here even though the @Transactional annotations don't exist yet as I plan on using them in further tests.
public class NotificationTypeEnumTest {
@PersistenceContext(unitName = "pu") // required to inject the correct EntityManager
private EntityManager em;
// these statements are
@Test
@Sql(statements = {"INSERT INTO MYAPP_ENUM (ENUM_ID, \"TYPE\", \"VALUE\") VALUES (MYAPP_ENUM_ID_SEQ.nextval, '" + NotificationTypeEnum.DTYPE + "', 'foo')"}, executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD)
@Sql(statements = {"DELETE FROM MYAPP_ENUM"}, executionPhase = Sql.ExecutionPhase.AFTER_TEST_METHOD)
public void canFetchNotificationTypeEnum() throws Exception {
TypedQuery<NotificationTypeEnum> query = em.createQuery("select a from NotificationTypeEnum a", NotificationTypeEnum.class); // notification type is just a subclass of the BaseEnum type
NotificationTypeEnum result = query.getSingleResult();
assertEquals("foo", result.getValue());
assertEquals(NotificationTypeEnum.DTYPE, result.getConfigType());
}
}
值得注意的类(class):
EntityManagerFactoryBuilder
- 我不喜欢工厂工厂,但是这个工厂在创建 EntityManagerFactory 的正确实现方面非常有用,而不依赖于任何 hibernate 特定类。可以用 @Autowired
注入(inject)。构建器 bean 本身是通过 HibernateJpaAutoConfiguration
类(扩展 JpaBaseConfiguration
)(由 @DataJpaTest
导入)配置的。JpaProperties
- 有助于在生成的 entitymanagerfactories 中维护 application.properties
配置。通过此配置类上方的 @EnableConfigurationProperties(JpaProperties.class)
注释启用。@PersistenceContext(unitName = "...")
- 我可以使用此注释在我的测试类中注入(inject)正确的 EntityManager
。关于java - @Sql 失败的 SQL 脚本 : The configured DataSource [*] (named 'fooDS' ) is not the one associated with transaction manager [*] (named 'fooTM' ),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46440300/
更新:将代码更改为立即调用并分配 dataSource ,但我仍然遇到相同的结果,但 sourceData.paginator 正在运行。 sourceData.filter 和 sourceData
我想以编程方式设置我的数据源的模型。像这样的东西: var ds = new kendo.data.DataSource({ //... }); var mod = kendo.data.Model.
我有一个多模块 maven 项目,我想将它与 一起使用tomcat7 maven插件并开始: mvn tomcat7:run 但我不知道如何配置 jndi 数据源。 我试图放入我的 pom.xml:
任何人都可以提供有关如何执行此操作的说明吗?我设置了几个不同的 JDBC 数据源,并希望能够配置用户使用不同的数据源运行相同的报告。例如。当用户A登录并运行报表A时,使用数据源1;当用户 B 登录并运
过去几周我从这个网站收集了许多有用的答案。我加入是为了对一些我认为最有帮助的答案+1,但目前还无法做到这一点。不过谢谢! 我的问题是 JBoss 7 AS 部署错误,我似乎无法追踪任何相关信息。它开始
我们遇到了一个 problem哪里 我们在一个 MDI 工作区中有两个相同窗口的实例,它们绑定(bind)到两个单独的对象模型。 对象模型覆盖了它们的 .Equals 和 .GetHashCode 方
当我运行我的独立 Web 应用程序时,spring 无法实例化数据源 bean。请注意,我不想在此项目中使用 JPA 或休眠。在这一点上我不知道为什么。我最好的猜测是依赖项或语法问题,但我无法找到解决
已结束。此问题正在寻求书籍、工具、软件库等的推荐。它不满足Stack Overflow guidelines 。目前不接受答案。 我们不允许提出寻求书籍、工具、软件库等推荐的问题。您可以编辑问题,以便
我的项目使用springBoot2,并且不需要连接数据库,但是springboot自动配置数据源并在启动项目时抛出异常。我已经添加了执行,但它不起作用 @SpringBootApplication(e
我指的是下面的链接来设置环回框架并创建简单的 API https://docs.strongloop.com/display/public/LB/Getting+started+with+LoopBa
我在 SPringBoot 中的数据源有问题。我想使用 JDBC 并从数据源获取数据,但出现错误:说明: com.example.My.MyApplication 中的字段 dataSource 需要
这是在我的 spring-servlet.xml 文件中定义的具有此 id 的 bean 这是完整的堆栈跟踪 SEVERE: Exception sending context initialize
我正在尝试使用 Spring、Maven 和 Hibernate 创建一个访问 sql server 数据库的应用程序。当我尝试运行应用程序时出现以下错误: Exception in thread "
当我运行我的网络应用程序时抛出以下错误。 Exception encountered during context initialization - cancelling refresh attemp
我正在研究 Spring Boot JDBC MYSQL 示例。在这个例子中,我使用了 1.3.1.RELEASE spring boot starter 版本,当时我使用了以下 2 spring.d
Feb 20, 2012 6:30:45 AM org.apache.catalina.core.ApplicationContext log INFO: Initializing Spring ro
我引用了网址:https://o7planning.org/en/11727/understanding-spring-cloud-config-client-with-example没有任何自定义,
spring.jpa.hibernate.ddl-auto=update spring.datasource.url=jdbc:mysql://localhost:3306/study?serverT
我有一个多线程作业(同时运行 6 个作业),这些作业使用 3 个数据源(第一个数据源上有 2 个,第二个数据源上有另外 2 个,第三个数据源上有最后 2 个)。 /* *************
我正在尝试实现从CurrencyExchange模块到CurrencyConvert的开放字段调用,但我被这个错误卡住了。有谁能帮帮我吗?我已经检查了其他答案,并试图添加#spring.datasou
我是一名优秀的程序员,十分优秀!