我有一个 Kotlin (v1.1.4( Spring Boot (v2.0.0.BUILD-SNAPSHOT( 应用程序,运行在 Spring Data Neo4j (v5.0.0RC2(、Neo4j (v3.2.1( 和 Neo4j OGM (v3.0.0( 中。
尝试将自定义 JPA@Query
与具有自定义AttributeConverter
的字段一起使用时,我收到以下错误。
堆栈跟踪:
org.springframework.dao.InvalidDataAccessResourceUsageException: Error executing Cypher; Code: Neo.ClientError.Statement.TypeError; Description: Property values can only be of primitive types or arrays thereof; nested exception is org.neo4j.ogm.exception.CypherException: Error executing Cypher; Code: Neo.ClientError.Statement.TypeError; Description: Property values can only be of primitive types or arrays thereof
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at org.springframework.data.neo4j.transaction.SessionFactoryUtils.convertOgmAccessException(SessionFactoryUtils.java:153)
at org.springframework.data.neo4j.repository.support.SessionBeanDefinitionRegistrarPostProcessor.translateExceptionIfPossible(SessionBeanDefinitionRegistrarPostProcessor.java:71)
at org.springframework.dao.support.ChainedPersistenceExceptionTranslator.translateExceptionIfPossible(ChainedPersistenceExceptionTranslator.java:59)
at org.springframework.dao.support.DataAccessUtils.translateIfNecessary(DataAccessUtils.java:216)
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:153)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
at org.springframework.data.repository.core.support.SurroundingTransactionDetectorMethodInterceptor.invoke(SurroundingTransactionDetectorMethodInterceptor.java:61)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:212)
at com.sun.proxy.$Proxy158.createBelongsToRelationship(Unknown Source)
at com.yellowbird.mbi.service.StoreServiceImpl.updateVendorStoreRelationship(StoreServiceImpl.kt:26)
at com.yellowbird.mbi.service.StoreServiceImpl$$FastClassBySpringCGLIB$$e7299ffb.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:747)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
at org.springframework.aop.interceptor.AbstractTraceInterceptor.invoke(AbstractTraceInterceptor.java:133)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:689)
at com.yellowbird.mbi.service.StoreServiceImpl$$EnhancerBySpringCGLIB$$3e3291f9.updateVendorStoreRelationship(<generated>)
at com.yellowbird.mbi.service.StoreServiceIT.givenVendorId13_getVendorByVendorId_returnsVendorWithId13(StoreServiceIT.kt:28)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.springframework.test.context.junit4.statements.RunBeforeTestExecutionCallbacks.evaluate(RunBeforeTestExecutionCallbacks.java:73)
at org.springframework.test.context.junit4.statements.RunAfterTestExecutionCallbacks.evaluate(RunAfterTestExecutionCallbacks.java:83)
at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75)
at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86)
at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:251)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:97)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:190)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
Caused by: org.neo4j.ogm.exception.CypherException: Error executing Cypher; Code: Neo.ClientError.Statement.TypeError; Description: Property values can only be of primitive types or arrays thereof
at org.neo4j.ogm.drivers.embedded.request.EmbeddedRequest.executeRequest(EmbeddedRequest.java:176)
at org.neo4j.ogm.drivers.embedded.request.EmbeddedRequest.execute(EmbeddedRequest.java:78)
at org.neo4j.ogm.session.delegates.ExecuteQueriesDelegate.executeAndMap(ExecuteQueriesDelegate.java:117)
at org.neo4j.ogm.session.delegates.ExecuteQueriesDelegate.query(ExecuteQueriesDelegate.java:86)
at org.neo4j.ogm.session.Neo4jSession.query(Neo4jSession.java:391)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.data.neo4j.transaction.SharedSessionCreator$SharedSessionInvocationHandler.invoke(SharedSessionCreator.java:131)
at com.sun.proxy.$Proxy145.query(Unknown Source)
at org.springframework.data.neo4j.repository.query.GraphQueryExecution$SingleEntityExecution.execute(GraphQueryExecution.java:74)
at org.springframework.data.neo4j.repository.query.GraphRepositoryQuery.doExecute(GraphRepositoryQuery.java:77)
at org.springframework.data.neo4j.repository.query.AbstractGraphRepositoryQuery.execute(AbstractGraphRepositoryQuery.java:51)
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.doInvoke(RepositoryFactorySupport.java:565)
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.invoke(RepositoryFactorySupport.java:549)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
at org.springframework.data.projection.DefaultMethodInvokingMethodInterceptor.invoke(DefaultMethodInvokingMethodInterceptor.java:60)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:294)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:98)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:139)
... 47 more
Caused by: org.neo4j.graphdb.QueryExecutionException: Property values can only be of primitive types or arrays thereof
at org.neo4j.kernel.impl.query.QueryExecutionKernelException.asUserException(QueryExecutionKernelException.java:35)
at org.neo4j.kernel.impl.factory.ClassicCoreSPI.executeQuery(ClassicCoreSPI.java:82)
at org.neo4j.kernel.impl.factory.GraphDatabaseFacade.execute(GraphDatabaseFacade.java:430)
at org.neo4j.kernel.impl.factory.GraphDatabaseFacade.execute(GraphDatabaseFacade.java:413)
at org.neo4j.ogm.drivers.embedded.request.EmbeddedRequest.executeRequest(EmbeddedRequest.java:172)
... 69 more
Caused by: org.neo4j.kernel.impl.query.QueryExecutionKernelException: Property values can only be of primitive types or arrays thereof
at org.neo4j.cypher.internal.javacompat.ExecutionEngine.executeQuery(ExecutionEngine.java:65)
at org.neo4j.kernel.impl.factory.ClassicCoreSPI.executeQuery(ClassicCoreSPI.java:78)
... 72 more
Caused by: org.neo4j.cypher.CypherTypeException: Property values can only be of primitive types or arrays thereof
at org.neo4j.cypher.internal.compatibility.v3_2.exceptionHandler$.cypherTypeException(exceptionHandler.scala:60)
at org.neo4j.cypher.internal.compatibility.v3_2.exceptionHandler$.cypherTypeException(exceptionHandler.scala:27)
at org.neo4j.cypher.internal.frontend.v3_2.CypherTypeException.mapToPublic(CypherException.scala:48)
at org.neo4j.cypher.internal.compatibility.v3_2.exceptionHandler$runSafely$.apply(exceptionHandler.scala:95)
at org.neo4j.cypher.internal.compatibility.v3_2.Compatibility$ExecutionPlanWrapper.run(Compatibility.scala:100)
at org.neo4j.cypher.internal.PreparedPlanExecution.execute(PreparedPlanExecution.scala:26)
at org.neo4j.cypher.internal.ExecutionEngine.execute(ExecutionEngine.scala:107)
at org.neo4j.cypher.internal.javacompat.ExecutionEngine.executeQuery(ExecutionEngine.java:61)
... 73 more
Caused by: org.neo4j.cypher.internal.frontend.v3_2.CypherTypeException: Property values can only be of primitive types or arrays thereof
at org.neo4j.cypher.internal.compiler.v3_2.helpers.CastSupport$.getConverter(CastSupport.scala:106)
at org.neo4j.cypher.internal.compiler.v3_2.mutation.makeValueNeoSafe$.transformTraversableToArray(makeValueNeoSafe.scala:54)
at org.neo4j.cypher.internal.compiler.v3_2.mutation.makeValueNeoSafe$.apply(makeValueNeoSafe.scala:29)
at org.neo4j.cypher.internal.compiler.v3_2.pipes.BaseRelationshipPipe.org$neo4j$cypher$internal$compiler$v3_2$pipes$BaseRelationshipPipe$$setProperty(CreateRelationshipPipe.scala:77)
at org.neo4j.cypher.internal.compiler.v3_2.pipes.BaseRelationshipPipe$$anonfun$setProperties$1$$anonfun$apply$1.apply(CreateRelationshipPipe.scala:63)
at org.neo4j.cypher.internal.compiler.v3_2.pipes.BaseRelationshipPipe$$anonfun$setProperties$1$$anonfun$apply$1.apply(CreateRelationshipPipe.scala:62)
at scala.collection.immutable.Map$Map3.foreach(Map.scala:161)
at org.neo4j.cypher.internal.compiler.v3_2.pipes.BaseRelationshipPipe$$anonfun$setProperties$1.apply(CreateRelationshipPipe.scala:62)
at org.neo4j.cypher.internal.compiler.v3_2.pipes.BaseRelationshipPipe$$anonfun$setProperties$1.apply(CreateRelationshipPipe.scala:56)
at scala.Option.foreach(Option.scala:257)
at org.neo4j.cypher.internal.compiler.v3_2.pipes.BaseRelationshipPipe.setProperties(CreateRelationshipPipe.scala:56)
at org.neo4j.cypher.internal.compiler.v3_2.pipes.BaseRelationshipPipe.org$neo4j$cypher$internal$compiler$v3_2$pipes$BaseRelationshipPipe$$createRelationship(CreateRelationshipPipe.scala:45)
at org.neo4j.cypher.internal.compiler.v3_2.pipes.BaseRelationshipPipe$$anonfun$internalCreateResults$1.apply(CreateRelationshipPipe.scala:38)
at org.neo4j.cypher.internal.compiler.v3_2.pipes.BaseRelationshipPipe$$anonfun$internalCreateResults$1.apply(CreateRelationshipPipe.scala:38)
at scala.collection.Iterator$$anon$11.next(Iterator.scala:409)
at scala.collection.Iterator$class.foreach(Iterator.scala:893)
at scala.collection.AbstractIterator.foreach(Iterator.scala:1336)
at org.neo4j.cypher.internal.compiler.v3_2.pipes.EagerAggregationPipe.internalCreateResults(EagerAggregationPipe.scala:89)
at org.neo4j.cypher.internal.compiler.v3_2.pipes.PipeWithSource.createResults(Pipe.scala:82)
at org.neo4j.cypher.internal.compiler.v3_2.pipes.PipeWithSource.createResults(Pipe.scala:79)
at org.neo4j.cypher.internal.compiler.v3_2.pipes.PipeWithSource.createResults(Pipe.scala:79)
at org.neo4j.cypher.internal.compiler.v3_2.executionplan.DefaultExecutionResultBuilderFactory$ExecutionWorkflowBuilder.createResults(DefaultExecutionResultBuilderFactory.scala:96)
at org.neo4j.cypher.internal.compiler.v3_2.executionplan.DefaultExecutionResultBuilderFactory$ExecutionWorkflowBuilder.build(DefaultExecutionResultBuilderFactory.scala:74)
at org.neo4j.cypher.internal.compiler.v3_2.BuildInterpretedExecutionPlan$$anonfun$getExecutionPlanFunction$1.apply(BuildInterpretedExecutionPlan.scala:103)
at org.neo4j.cypher.internal.compiler.v3_2.BuildInterpretedExecutionPlan$$anonfun$getExecutionPlanFunction$1.apply(BuildInterpretedExecutionPlan.scala:86)
at org.neo4j.cypher.internal.compiler.v3_2.BuildInterpretedExecutionPlan$$anon$1.run(BuildInterpretedExecutionPlan.scala:55)
at org.neo4j.cypher.internal.compatibility.v3_2.Compatibility$ExecutionPlanWrapper$$anonfun$run$1.apply(Compatibility.scala:102)
at org.neo4j.cypher.internal.compatibility.v3_2.Compatibility$ExecutionPlanWrapper$$anonfun$run$1.apply(Compatibility.scala:100)
at org.neo4j.cypher.internal.compatibility.v3_2.exceptionHandler$runSafely$.apply(exceptionHandler.scala:90)
... 77 more
这是我的转换器:
class ZonedDateTimeStringConverter : AttributeConverter<ZonedDateTime, String> {
companion object {
private val DATE_TIME_FORMAT = DateTimeFormatter.ISO_OFFSET_DATE_TIME
}
override fun toGraphProperty(value: ZonedDateTime?): String? = when (value) {
null -> null
else -> DATE_TIME_FORMAT.format(value)
}
override fun toEntityAttribute(value: String?): ZonedDateTime? = when (value) {
null -> null
else -> ZonedDateTime.parse(value, DATE_TIME_FORMAT)
}
}
我这里有一个关系实体:
@RelationshipEntity(type = "PART_OF")
data class PartOf(
/*
* @GraphId, @StartNode, @EndNode defined here)
*/
@Convert(ZonedDateTimeStringConverter::class)
var sinceDate: ZonedDateTime? = null
)
我的 JPA 查询如下:
@Query("MATCH (s:EntityOne {identifier: {entityOneIdentifier}})" +
" MATCH (v:EntityTwo {identifier: {entitiyTwoIdentifier}})" +
" CREATE (v)-[:PART_OF {createDate: {createDate}, sinceDate: {sinceDate}, active: {active}}]->(s) " +
" RETURN count(s) > 0")
fun createPartOfRelationship(@Param("entityOneIdentifier") entityOneId: Long,
@Param("entityTwoIdentifier") entityTwoId: Long,
@Param("createDate") createDate: ZonedDateTime,
@Param("sinceDate") sinceDate: ZonedDateTime,
@Param("active") active: Boolean): Boolean
在线查看 Neo4j 参考的 Spring 数据,看起来我已经准备好了一切。OGM 正确查看转换器(我能够调试并看到正在创建/命中类内部的静态companion object
。
所以,我认为Spring Data可能需要了解转换器。因此,根据文档,我在 Spring 配置中添加了一个ConversionService
。
@Bean
fun conversionService(@Autowired sessionFactory: SessionFactory): ConversionService =
MetaDataDrivenConversionService(sessionFactory.metaData())
这确实可以使用像Spring Data Neo4j文档所说的java.util.Date
,它应该(其自动配置(如下所述:http://docs.spring.io/spring-data/neo4j/docs/4.0.0.RELEASE/reference/html/#reference_programming-model_conversion
有没有人有任何建议可以尝试或为什么会发生这种情况?
不可能有这样的参数
@Param("createDate") createDate: ZonedDateTime
@Query
注释存储库方法。
在这种情况下,目标类型是String
,但可以是Integer
、Double
等,查询将是相同的 - SDN 不知道您需要转换为的类型,因此您需要自己进行转换以正确的类型(对于查询参数(。