2017-08-16 2 views
1

J'ai une application Spring boot neo4j et je veux stocker les utilisateurs dans la base de données Neo4j. J'ai suivi les instructions trouvées here. La configuration Neo4j est la suivante:Spring Data Neo4j InvalidDataAccessApiUsageException: La transaction n'est pas en cours pour ce thread

@Configuration 
@EnableWebMvc 
@ComponentScan({"eu.bm"}) 
@EnableNeo4jRepositories("eu.bm.repository") 
@EnableTransactionManagement 
public class bmConfiguration extends WebMvcConfigurerAdapter { 

@Bean 
public OpenSessionInViewInterceptor openSessionInViewInterceptor() { 
    OpenSessionInViewInterceptor openSessionInViewInterceptor = 
      new OpenSessionInViewInterceptor(); 
    openSessionInViewInterceptor.setSessionFactory(sessionFactory()); 
    return openSessionInViewInterceptor; 
} 

public void addInterceptors(InterceptorRegistry registry) { 
    registry.addWebRequestInterceptor(openSessionInViewInterceptor()); 
} 

@Bean 
public static SessionFactory sessionFactory() { 
    return new SessionFactory("eu.bm.domain"); 
} 

@Bean 
public Neo4jTransactionManager transactionManager() throws Exception { 
    return new Neo4jTransactionManager(sessionFactory()); 
} 

Le référentiel utilisateur est ceci:

@Repository 
public interface UserRepository extends GraphRepository<User>{ 

@Query("MATCH (user:User) where user.name={0} return user ") 
User findUser(String username); 

@Query("MATCH (user:User) where user.name={0} delete user ") 
User deleteUser(String username); 

@Query("match (user:User) delete user") 
User deleteAllUsers(); 

} 

J'ai aussi cette configuration de service de gestion de l'utilisateur:

@Component 
public interface UserManagementService { 

List<User> listAll(); 

User save(User user); 

User findUser(String username); 
} 

qui est mis en œuvre ici:

@Service 
@Transactional 
public class UserManagementServiceImpl implements UserManagementService { 

private UserRepository userRepository; 

@Autowired 
public UserManagementServiceImpl(UserRepository userRepository) {this.userRepository = userRepository;} 

@Override 
public List<User> listAll() { 
    List<User> users = new ArrayList<>(); 
    userRepository.findAll().forEach(users::add); 
    return users; 
} 

@Override 
public User save(User user) { 
    userRepository.save(user); 
    return user; 
} 

@Override 
public User findUser(String username) { 
    return userRepository.findUser(username); 
} 

je puis effectuer un simple test d'écriture-lecture comme ceci:

@RunWith(SpringJUnit4ClassRunner.class) 
@SpringBootTest 
public class DatabaseConnectionTest { 

// User 1 
private static final String UNAME1 = "Paul"; 
private static final String EMAIL1 = "[email protected]"; 
private static final String PASSWORD1 = "[email protected]"; 
private static final String USERNAME1 = "paul"; 

@Autowired 
private UserRepository userRepository; 

@Before 
public void setUp() throws Exception { 

    // Clear database before adding new user 
    userRepository.deleteAllUsers(); 

    // Creating user 
    User user = new User(UNAME1, USERNAME1, PASSWORD1, EMAIL1); 
    userRepository.save(user); 
} 

@Test 
public void testPersistence() { 

    Assert.assertEquals(UNAME1, userRepository.findUser(UNAME1).getName()); 
    Assert.assertEquals(USERNAME1, userRepository.findUser(UNAME1).getUsername()); 

} 

Le résultat de ce qui précède est cette erreur:

2017-08-16 14:59:38.990 INFO 6496 --- [ main] e.b.repository.DatabaseConnectionTest : Started DatabaseConnectionTest in 7.131 seconds (JVM running for 8.331) 2017-08-16 14:59:39.872 INFO 6496 --- [ main] o.n.o.drivers.http.request.HttpRequest : Thread: 1, url: http://localhost:7474/db/data/transaction/39 , request: {"statements":[{"statement":"UNWIND {rows} as row CREATE (n: User) SET n=row.props RETURN row.nodeRef as ref, ID(n) as id, row.type as type","parameters":{"rows":[{"nodeRef":-1821370276,"type":"node","props":{"password":"[email protected]","name":"Paul","email":"[email protected]","username":"paul"}}]},"resultDataContents":["row"],"includeStats":false}]} 2017-08-16 14:59:40.358 ERROR 6496 --- [ main] o.s.d.n.t.Neo4jTransactionManager : Commit exception overridden by rollback exception

org.springframework.dao.InvalidDataAccessApiUsageException: Transaction is not current for this thread; nested exception is org.neo4j.ogm.exception.TransactionManagerException: Transaction is not current for this thread

  • Pourquoi userRepository.save (utilisateur) crée l'enregistrement dans la base de données, mais jette l'exception?
  • Que signifie exactement "Transaction is current for this thread"?
  • Pourquoi userRepository.save (utilisateur) échoue-t-il finalement mais userRepository.deleteAllUsers() fonctionne?

modifier: Mon dependencies.gradle comprend les éléments suivants:

compile group: 'org.springframework.boot', name: 'spring-boot-starter-data-neo4j', version: '1.5.6.RELEASE' 
//compile group: 'org.springframework.data', name: 'spring-data-neo4j', version: '4.2.6.RELEASE' 
compile group: 'org.neo4j', name: 'neo4j-ogm-core', version: '2.1.3' 
//compile group: 'org.neo4j', name: 'neo4j-ogm-bolt-driver', version: '2.1.3' 
runtime group: 'org.neo4j', name: 'neo4j-ogm-http-driver', version: '2.1.3' 
compile('org.springframework.boot:spring-boot-starter-security') 
compile('org.springframework.boot:spring-boot-starter-thymeleaf') 
compile('org.springframework.boot:spring-boot-starter-web') 
compile group: 'org.springframework.boot', name: 'spring-boot-starter-actuator', version: '1.5.4.RELEASE' 
testCompile('org.springframework.boot:spring-boot-starter-test') 
+0

Salut, pouvez-vous fournir des versions des bibliothèques utilisées? (démarrage du printemps, sdn, ogm ..) Aussi le téléchargement de l'échantillon complet aiderait. La clé est '@ EnableTransactionManagement' - ce que vous avez, donc pour une raison quelconque, cela ne fonctionne pas. –

+0

@ frant.hartm Merci. J'ai ajouté les dépendances utilisées dans mon build.gradle ci-dessus. Que voulez-vous dire par "échantillon complet"? – PaulB

+0

Un projet que nous pourrions télécharger et essayer. –

Répondre

1

Votre haricot SessionFactory ne doit pas être déclarée comme static:

@Bean 
public static SessionFactory sessionFactory() { 
    return new SessionFactory("eu.bm.domain"); 
} 

devrait être

@Bean 
public SessionFactory sessionFactory() { 
    return new SessionFactory("eu.bm.domain"); 
} 

"Arbitration is current for this thread" signifie que quelque chose essaie de valider une transaction qui est différente de la transaction tx actuelle dans un contexte local de threads.

Vous utilisez la gestion des transactions par défaut - elle crée une transaction autour des appels du référentiel. Lorsque le bean SessionFactory est défini comme étant statique, la session ne voit pas la transaction dans thread locale (celle démarrée par la gestion tx par défaut) et en crée une nouvelle, tente de la valider et l'exception apparaît.

+0

Wow ... Je regardais ce code depuis 2 jours maintenant et ne le remarquerais jamais.Merci beaucoup. – PaulB