Я использую пружинную загрузку 2 и зависимость neo4j от data (которая, я думаю, приносит sdn 5.x) в дополнение к neo4j-ogm 3.1.1 для управления моим постоянством.Я отметил, что Neo4jTransactionManager по умолчанию не поддерживает вложенные транзакции или требует нового распространения.
Я хотел бы, чтобы мой метод обслуживания выполнял, по существу, несколько шагов в отдельных транзакциях.
Для достижения того, что я хочу, я прибегнул к поддержке асинхронной / многопоточности Spring, чтобы эффективно форсировать новый сеанс и транзакцию по шагам в моем методе обслуживания, как показано ниже.Что я хотел бы знать, есть ли лучший способ решить эту проблему?
Мне кажется, что я могу легко создавать отдельные транзакции / единицы работы, но готовое решение data neo4j для пружин ограничивает это.
Мой метод обслуживания, первый шагЯ хочу изолировать уже в отдельном сервисе, отмеченном здесь вызовом connectionService.deleteDiagramConnections (figure.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;
}
}