Hello,
I am trying to Migrate a Spring Boot 2 application from Neo4J 3 (ogm) to Spring Boot 3.2 + Neo4J 5
The project basically loads some data from a MSSQL server database into a standalone Neo4J instance. Then, Neo4j is used for querying.
Project compiles perfectly, but I am getting following error while running the project:
Caused by: org.springframework.data.mapping.MappingException: Couldn't find PersistentEntity for type class java.util.HashMap
at org.springframework.data.mapping.context.MappingContext.getRequiredPersistentEntity(MappingContext.java:80)
at org.springframework.data.neo4j.repository.support.Neo4jRepositoryFactory.getEntityInformation(Neo4jRepositoryFactory.java:66)
at org.springframework.data.neo4j.repository.support.Neo4jRepositoryFactory.getTargetRepository(Neo4jRepositoryFactory.java:73)
at org.springframework.data.repository.core.support.RepositoryFactorySupport.getRepository(RepositoryFactorySupport.java:317)
at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.lambda$afterPropertiesSet$5(RepositoryFactoryBeanSupport.java:279)
at org.springframework.data.util.Lazy.getNullable(Lazy.java:135)
at org.springframework.data.util.Lazy.get(Lazy.java:113)
at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.afterPropertiesSet(RepositoryFactoryBeanSupport.java:285)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1820)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1769)
... 16 common frames omitted
Repo:
package com.harsh.neo4jdemo.graphdb.repo;
import org.springframework.data.neo4j.repository.Neo4jRepository;
import org.springframework.data.neo4j.repository.query.Query;
import org.springframework.stereotype.Repository;
import java.util.HashMap;
import java.util.stream.Stream;
@Repository
public interface GraphWalk4uiRepo extends Neo4jRepository<HashMap<Object, Object>, Long> {
.
.
.
.
@Query(START_WALK_FROM_NON_PROCESS +
UPSTREAM_APOC_CALL +
KEEP_WALKING +
UPSTREAM_LINKS +
FINAL_COLLECT_UPSTREAM +
FINAL_RETURN)
Stream<HashMap<Object, Object>> walkGraphUpstreamStartFromNonProcess(String datasetName, String datasetApp, int maxLevel);
@Query(START_WALK_FROM_PROCESS +
UPSTREAM_APOC_CALL +
KEEP_WALKING +
UPSTREAM_LINKS +
FINAL_COLLECT_UPSTREAM +
FINAL_RETURN)
Stream<HashMap<Object, Object>> walkGraphUpstreamStartFromProcess(String processName, String processApp, int maxLevel);
@Query(START_WALK_FROM_NON_PROCESS +
DOWNSTREAM_APOC_CALL +
KEEP_WALKING_PROC_ONLY +
DOWNSTREAM_LINKS_PROC_ONLY +
FINAL_COLLECT_PROC_ONLY +
FINAL_RETURN)
Stream<HashMap<Object, Object>> walkGraphDownstreamStartFromNonProcessProcessesOnly(String datasetName, String datasetApp, int maxLevel);
}
pom.xml:
Spring Boot: 3.2.2
<properties>
<neo4j.version>5.16.0</neo4j.version>
<neo4j.apoc.version>5.16.1</neo4j.apoc.version>
</properties>
.
.
.
.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-neo4j</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.neo4j</groupId>
<artifactId>neo4j</artifactId>
<exclusions>
<exclusion>
<groupId>org.neo4j</groupId>
<artifactId>neo4j-slf4j-provider</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.neo4j.driver</groupId>
<artifactId>neo4j-java-driver</artifactId>
<version>5.17.0<version>
</dependency>
<dependency>
<groupId>org.neo4j.procedure</groupId>
<artifactId>apoc-core</artifactId>
<version>${neo4j.apoc.version}</version>
</dependency>
<dependency>
<groupId>org.neo4j.procedure</groupId>
<artifactId>apoc-common</artifactId>
<version>${neo4j.apoc.version}</version>
</dependency>
Neo4J Config:
package com.harsh.neo4jdemo.config;
import jakarta.annotation.Nonnull;
import org.neo4j.configuration.GraphDatabaseSettings;
import org.neo4j.configuration.connectors.BoltConnector;
import org.neo4j.configuration.helpers.SocketAddress;
import org.neo4j.cypherdsl.core.renderer.Dialect;
import org.neo4j.dbms.api.DatabaseManagementService;
import org.neo4j.dbms.api.DatabaseManagementServiceBuilder;
import org.neo4j.driver.AuthTokens;
import org.neo4j.driver.Driver;
import org.neo4j.driver.GraphDatabase;
import org.neo4j.graphdb.GraphDatabaseService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.neo4j.Neo4jProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.data.neo4j.config.AbstractNeo4jConfig;
import org.springframework.data.neo4j.core.DatabaseSelectionProvider;
import org.springframework.data.neo4j.repository.config.EnableNeo4jRepositories;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import java.nio.file.Path;
import java.util.List;
import static org.neo4j.configuration.GraphDatabaseSettings.DEFAULT_DATABASE_NAME;
@Configuration
@ComponentScan({"com.harsh.neo4jdemo.graphdb"})
@EnableNeo4jRepositories(basePackages = "com.harsh.neo4jdemo.graphdb.repo")
@EnableTransactionManagement
@Profile("!test")
public class Neo4JConfig extends AbstractNeo4jConfig {
@Value("${neo4j.db.path}")
private String pathname;
private final Neo4jProperties neo4jProperties;
@Autowired
public Neo4JConfig(Neo4jProperties neo4jProperties) {
this.neo4jProperties = neo4jProperties;
}
@Override
@Bean
@Nonnull
protected DatabaseSelectionProvider databaseSelectionProvider() {
return DatabaseSelectionProvider.createStaticDatabaseSelectionProvider(DEFAULT_DATABASE_NAME);
}
@Bean
@Nonnull
public org.neo4j.cypherdsl.core.renderer.Configuration cypherDslConfiguration() {
return org.neo4j.cypherdsl.core.renderer.Configuration.newConfig()
.withDialect(Dialect.NEO4J_5)
.build();
}
@Override
@Bean
@Nonnull
public Driver driver() {
Neo4jProperties.Authentication authentication = neo4jProperties.getAuthentication();
return GraphDatabase.driver(neo4jProperties.getUri(),
AuthTokens.basic(authentication.getUsername(), authentication.getPassword()));
}
@Bean
public GraphDatabaseService graphDatabaseService() {
DatabaseManagementService managementService = new DatabaseManagementServiceBuilder(Path.of(pathname))
.setConfig(BoltConnector.enabled, true )
.setConfig(GraphDatabaseSettings.default_listen_address, new SocketAddress("localhost", 7687))
.setConfig(GraphDatabaseSettings.default_advertised_address, new SocketAddress("localhost", 7687))
.setConfig(GraphDatabaseSettings.procedure_unrestricted, List.of("apoc.create", "apoc.path"))
.setConfig(GraphDatabaseSettings.procedure_allowlist, List.of("apoc.create", "apoc.path"))
.build();
GraphDatabaseService graphDatabaseService = managementService.database(DEFAULT_DATABASE_NAME);
registerShutdownHook(managementService);
return graphDatabaseService;
}
private static void registerShutdownHook(final DatabaseManagementService managementService) {
Runtime.getRuntime().addShutdownHook(new Thread(managementService::shutdown));
}
}
Main Class:
package com.harsh.neo4jdemo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
@SpringBootApplication
@EnableJpaRepositories(basePackages = "com.harsh.neo4jdemo.graphdb.jpa.datamodel.repo")
@EntityScan({"com.harsh.neo4jdemo.graphdb.datamodel.model"})
public class GraphDbMain {
public static void main(String[] args) {
SpringApplication.run(GraphDbMain.class, args);
}
}
application.properties:
spring.datasource.driver-class-name=com.microsoft.sqlserver.jdbc.SQLServerDriver
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.SQLServerDialect
spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
spring.datasource.url=jdbc:sqlserver://<Some personal URL I won't mention here>
spring.datasource.username=XXXXXXXXXX
spring.datasource.password=XXXXXXXXXX
spring.neo4j.uri=bolt://localhost:7687
spring.neo4j.authentication.username=neo4j
spring.neo4j.authentication.password=password
neo4j.db.path=D:/temp/neo4j.db
server.port=8080