mir*_*rko 5 java spring transactions spring-data-jpa
我正在尝试在只读数据源之上建立一个带有JPA存储库的简单Spring Boot项目,并且我希望将只读标志作为提示传播到底层JDBC驱动程序以进行性能优化,按照Spring Data JPA参考.
存储库实现如下所示:
public interface MyReadOnlyRepository extends JpaRepository<String, String> {}
Run Code Online (Sandbox Code Playgroud)
这是配置类:
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
entityManagerFactoryRef = "readOnlyEntityManagerFactory",
transactionManagerRef = "readOnlyTransactionManager",
basePackageClasses = ReadOnlyDbConfig.class)
public class ReadOnlyDbConfig {
@Bean(name = "readOnlyDataSource")
@ConfigurationProperties(prefix = "spring.datasource.ro")
public DataSource dataSource() {
return DataSourceBuilder.create().build();
}
@Bean(name = "readOnlyEntityManagerFactory")
public LocalContainerEntityManagerFactoryBean entityManagerFactory(
EntityManagerFactoryBuilder builder,
@Qualifier("readOnlyDataSource") DataSource dataSource) {
return builder
.dataSource(dataSource)
.packages(MyEntity.class)
.persistenceUnit("readOnly")
.build();
}
@Bean(name = "readOnlyTransactionManager")
public PlatformTransactionManager transactionManager(
@Qualifier("readOnlyEntityManagerFactory") EntityManagerFactory entityManagerFactory) {
return new JpaTransactionManager(entityManagerFactory);
}
}
Run Code Online (Sandbox Code Playgroud)
以及相关的YML属性:
spring:
datasource:
ro:
url: jdbc:postgresql://...
username: ...
password: ...
driver-class-name: org.postgresql.Driver
default-read-only: true
Run Code Online (Sandbox Code Playgroud)
为了测试它,我编写了一个针对dockerres PostgresSQL实例运行的简单测试:
@SpringBootTest(classes = TestApplication.class)
@RunWith(SpringRunner.class)
@ContextConfiguration(initializers = { PostgresInDockerInitializer.class })
public class MyReadOnlyStoreTest {
@Inject
private MyReadOnlyRepository repo;
@Test(expected = RuntimeException.class)
public void testIsReadOnly() {
repo.save("test");
}
}
Run Code Online (Sandbox Code Playgroud)
我只是为了测试标志是否设置而调用了save:我很欣赏只读标志只是作为JDBC驱动程序的提示,而不是作为写操作的保护机制.正如预期的那样,测试抛出异常("无法在只读事务中执行INSERT").
我的问题是,只要事务成功完成,JPA事务管理器就会将连接只读标志重置为false.因此,例如,此测试失败:
@Test(expected = RuntimeException.class)
public void testIsReadOnly() {
repo.findAll(); // <-- on commit, the transaction manager resets the read-only flag to false
repo.save("test");
}
Run Code Online (Sandbox Code Playgroud)
请注意,如果根据Spring Data JPA Reference使用@Transactional(readOnly = true)注释存储库,则会发生相同的情况.
有人可以解释为什么交易经理会这样做吗?除了将事务状态设置为仅回滚之外,是否有一种简单/更好的方法可以避免重置标志?
谢谢你的帮助.
| 归档时间: |
|
| 查看次数: |
605 次 |
| 最近记录: |