I am trying to update a node on Neo4J, but what ends up happening is that it creates a duplicate Node. I read that the update has to be in a single transaction and I added @Transactional, but still same result. Here is what I have. I tried the approach of reading and deleting the old node, and saving the new one and it appears to be working. But, I think that is not the right approach. Why the @Transactional annotation not working. Thank you.
@EnableNeo4JRepositories(com.example.graph.repo)
@EnableTransactionManagement
@org.springframework.contect.annotation.Configuration
public class Neo4JConfig {
@Bean
public Configuration configuration() {
Configuration cfg = new Configuration();
cfg.driverConfiguration()
.setDriverClassName("org.neo4j.ogm.drivers.http.driver.HttpDriver")
.setURI("http://neo4j:neo4j@localhost:7474");
return cfg;
}
@Bean
public SessionFactory sessionFactory() {
return new SessionFactory(configuration(), "com.example");
}
@Bean
public Neo4jTransactionManager transactionManager() {
return new Neo4JTransactionManager(sessionFactory());
}
}
@Service
public class UserService{
@Autowired
UserRepository userRepository;
@Transactional
public void updateUser(User user) {
User existingUser = userRepository.getExistingUser(user.getUserName());
if(existingUser != null ) {
user.setSomeValue(existingUser.getSomeValue());
userRepository.save(user);
}
}
}
Spring AOP uses JDK Proxy mechanism by default. It means that you must invoke @Transactional
method via interface method.
So you should split your service into interface UserService
and implementation (say UserServiceImpl
), autowire the interface into the code where you currently autowire the impementation, and then invoke transactional method via interface.
P.S. Another approach is to force Spring to use CGLIB as long as this mechanism is not limited to interfaces. More details for both mechanisms https://docs.spring.io/spring/docs/3.0.0.M3/reference/html/ch08s06.html