除了neo4j-ogm 3.1.1之外,我还使用spring boot 2和spring数据neo4j依赖项(我认为它带来了sdn 5.x)来管理我的持久性。我注意到默认的Neo4jTransactionManager不支持嵌套事务或需要新的传播。
我想做的是让我的服务方法在单独的事务中执行基本上多个步骤。
为了实现我想要的功能,我依靠spring的异步/多线程支持来有效地强制围绕服务方法中的步骤进行新的会话和事务,如下所示。我想知道的是,有没有更好的方法来解决这个问题?
我觉得我应该能够轻松地创建单独的事务/工作单元,但是开箱即用的spring数据neo4j解决方案对此有所限制。
我的服务方法,我想隔离的第一步已经在一个单独的服务中,该服务在此处标记为connectionService.deleteDiagramConnections(diagram.getId());
@Retryable(value = TransientException.class,exceptionExpression="#{message.contains('RWLock')}", maxAttempts = 5)
public Diagram update(final Diagram diagram) throws GUMLException {
AtomicReference<Diagram> result = new AtomicReference<Diagram>();
AtomicReference<Object> isComplete = new AtomicReference<Object>();
isComplete.set(false);
ListenableFuture future = connectionService.deleteDiagramConnections(diagram.getId());
future.addCallback(new ListenableFutureCallback() {
@Override
public void onFailure(Throwable throwable) {
logger.error(throwable);
}
@Override
public void onSuccess(Object o) {
for (Connection connection : diagram.getConnections()) {
connection.setId(null);
if (connection.getId() != null && connection.getMoveablePoints() != null) {
for (MoveablePoint mp : connection.getMoveablePoints()) {
mp.setId(null);
}
}
}
isComplete.set(true);
}
});
while ((boolean)isComplete.get() == false) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
throw new GUMLException(Severity.ERROR, e.getMessage());
}
if ((boolean)isComplete.get() == true)
result.set(umlDiagramRepository.save(diagram));
}
return result.get();
}
连接服务:
@Async
@Override
public ListenableFuture<String> deleteDiagramConnections(long diagramId) throws GUMLException {
connectionRepository.deleteDiagramConnections(diagramId);
return new AsyncResult<String>("delete complete");
}
这是我的测试应用配置
@org.springframework.context.annotation.Configuration
@ComponentScan(basePackages = "au.com.guml", lazyInit = true)
@EnableTransactionManagement
@EnableAsync
public class TestConfig {
@Bean
public org.neo4j.ogm.config.Configuration configuration() {
org.neo4j.ogm.config.Configuration configuration = new org.neo4j.ogm.config.Configuration.Builder()
.uri("bolt://localhost")
.credentials("neo4j", "password")
.build();
return configuration;
}
// @Bean
// public org.neo4j.ogm.config.Configuration configuration() {
// org.neo4j.ogm.config.Configuration configuration = new org.neo4j.ogm.config.Configuration.Builder()
// .uri("http://neo4j:password@localhost:7474")
// .build();
// return configuration;
// }
// @Bean
// public Configuration getConfiguration() {
//
// Configuration config = new Configuration();
// config
// .driverConfiguration()
// .setDriverClassName("org.neo4j.ogm.drivers.http.driver.HttpDriver")
// .setURI("http://neo4j:password@localhost:7474")
// .setCredentials("neo4j","password");
//
// return config;
// }
@Bean
public SessionFactory sessionFactory() {
// with domain entity base package(s)
return new SessionFactory(configuration() ,"au.com.guml.domain");
}
@Bean
public Neo4jTransactionManager transactionManager() {
return new Neo4jTransactionManager(sessionFactory());
}
// @Bean
// public TaskExecutor syncTaskExecutor () {
// SyncTaskExecutor syncTaskExecutor = new SyncTaskExecutor();
// return syncTaskExecutor;
// }
@Bean
public TaskExecutor threadPoolTaskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(4);
executor.setMaxPoolSize(4);
executor.setThreadNamePrefix("default_task_executor_thread");
executor.initialize();
return executor;
}
}
答案 0 :(得分:0)
因此,事实证明,我要做的就是将neo4j ogm会话注入我的服务并调用session.getTransaction().commit();
然后我在外部服务调用中将连接ID设置为null,并且它们都被添加为新连接。