gpt4 book ai didi

spring-data-neo4j v6 : No converter found capable of converting from type [MyDTO] to type [org. neo4j.driver.Value]

转载 作者:行者123 更新时间:2023-12-05 04:46:14 24 4
gpt4 key购买 nike

情况

我正在将 kotlin spring data neo4j 应用程序从 spring-data-neo4j 版本 5.2.0.RELEASE 迁移到版本 6.0.11.

原始应用程序有几个带有自定义查询的存储库接口(interface),这些接口(interface)将一些 DTO 作为参数,并使用各种 DTO 字段来构造查询。所有这些类型的查询目前都失败了

org.springframework.core.convert.ConverterNotFoundException: No converter found capable of converting from type [MyDTO] to type [org.neo4j.driver.Value]

reference documentation for spring-data-neo4j v6仅提供示例,其中传递给 @Repository 接口(interface)的自定义查询方法的参数与与该存储库关联的 @Node 类的类型相同。文档没有明确说明只允许使用 Node 类的参数。

问题

在 spring-data-neo4j 的 @Repository 接口(interface)中,有没有办法将任意 DTO(不是 @Node 类)传递给自定义查询方法v6 好像在 v5 中是可能的?

代码示例

示例节点实体

@Node
data class MyEntity(
@Id
val attr1: String,
val attr2: String,
val attr3: String
)

示例 DTO

data class MyDTO(
val field1: String,
val field2: String
)

存储库界面示例

@Repository
interface MyRepository : PagingAndSortingRepository<MyEntity, String> {

// ConverterNotFoundException is thrown when this method is called
@Query("MATCH (e:MyEntity {attr1: {0}.field1}) " +
"CREATE (e)-[l:LINK]->(n:OtherEntity {attr2: {0}.field2))")
fun doSomethingWithDto(dto: MyDTO)
}

目前尝试过的解决方案

将 DTO 注释为节点实体

基于引用文档中的以下内容 https://docs.spring.io/spring-data/neo4j/docs/current/reference/html/#custom-queries.parameters

Mapped entities (everything with a @Node) passed as parameter to afunction that is annotated with a custom query will be turned into anested map.

@Node
data class MyDTO(
@Id
val field1: String,
val field2: String
)

在自定义查询中将 {0} 替换为 $0

基于引用文档中的以下内容 https://docs.spring.io/spring-data/neo4j/docs/current/reference/html/#custom-queries.parameters

You do this exactly the same way as in a standard Cypher query issuedin the Neo4j Browser or the Cypher-Shell, with the $ syntax (fromNeo4j 4.0 on upwards, the old {foo} syntax for Cypher parameters hasbeen removed from the database).

...

[In the given listing] we are referring to the parameter by its name.You can also use $0 etc. instead.

@Repository
interface MyRepository : PagingAndSortingRepository<MyEntity, String> {

// ConverterNotFoundException is thrown when this method is called
@Query("MATCH (e:MyEntity {attr1: $0.field1}) " +
"CREATE (e)-[l:LINK]->(n:OtherEntity {attr2: $0.field2))")
fun doSomethingWithDto(dto: MyDTO)
}

详情

  • spring-boot-starter: v2.4.10
  • spring-data-neo4j: v6.0.12
  • neo4j-java-driver: v4.1.4
  • Neo4j 服务器版本:v3.5.29

最佳答案

RTFM Custom conversions ...

我自己找到了解决方案。希望其他人也可以从中受益。

解决方案

创建自定义转换器

import mypackage.model.*
import com.fasterxml.jackson.core.type.TypeReference
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
import org.neo4j.driver.Value
import org.neo4j.driver.Values
import org.springframework.core.convert.TypeDescriptor
import org.springframework.core.convert.converter.GenericConverter
import org.springframework.core.convert.converter.GenericConverter.ConvertiblePair
import java.util.HashSet

class DtoToNeo4jValueConverter : GenericConverter {
override fun getConvertibleTypes(): Set<ConvertiblePair>? {
val convertiblePairs: MutableSet<ConvertiblePair> = HashSet()
convertiblePairs.add(ConvertiblePair(MyDTO::class.java, Value::class.java))
return convertiblePairs
}

override fun convert(source: Any?, sourceType: TypeDescriptor, targetType: TypeDescriptor?): Any? {
return if (MyDTO::class.java.isAssignableFrom(sourceType.type)) {
// generic way of converting an object into a map
val dataclassAsMap = jacksonObjectMapper().convertValue(source as MyDTO, object :
TypeReference<Map<String, Any>>() {})
Values.value(dataclassAsMap)
} else null
}
}

在配置中注册自定义转换器

import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.data.neo4j.core.convert.Neo4jConversions
import org.springframework.core.convert.converter.GenericConverter
import java.util.*


@Configuration
class MyNeo4jConfig {
@Bean
override fun neo4jConversions(): Neo4jConversions? {
val additionalConverters: Set<GenericConverter?> = Collections.singleton(DtoToNeo4jValueConverter())
return Neo4jConversions(additionalConverters)
}
}

关于spring-data-neo4j v6 : No converter found capable of converting from type [MyDTO] to type [org. neo4j.driver.Value],我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68897676/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com