我以某种方式解决了这个问题。
我使用 Spring 的 Converter 和 ConverterFactory 可能将我的 @Entity 对象隐式转换为 Long ,反之亦然。
@NodeEntity 如下所示(代码在 Scala 中 - 但与 Java 没有相关差异):
@NodeEntity
class ImplicitUser {
@GraphId
var id: java.lang.Long = _
@Indexed(indexName="username", indexType=IndexType.FULLTEXT)
var username : String = _
@GraphProperty(propertyType = classOf[java.lang.Long])
var person : Person = _
override def toString =
"User %d %s".format(id, username)
}
相关部分是:
@GraphProperty(propertyType = classOf[java.lang.Long])
var person : Person = _
因为这告诉 neo4j 将该字段作为 Long 并尝试找到一个 Spring 转换器。因此需要定义 Spring 转换。为此,我定义了一个特征,该特征将 JPA @Entity 定义为具有 Long id:
trait JpaLongId {
@Id @GeneratedValue
var id: Long = -1
}
更简单的转换器之一是从对象到 Id 的转换器:
class JpaLongIdToLong extends Converter[JpaLongId, java.lang.Long] {
def convert(source : JpaLongId) : java.lang.Long = {
long2Long(source.id)
}
}
另一方面,我必须定义一个工厂以允许 EntityManager 的 DI:
@Component
class LongToJpaLongIdFactory extends ConverterFactory[java.lang.Long, JpaLongId] {
def getConverter[T <: JpaLongId](`type`: Class[T]): Converter[java.lang.Long, T] = {
return new LongToJpaLongId(`type`, em)
}
@PersistenceContext
var em: EntityManager = null
}
class LongToJpaLongId[T <: JpaLongId] extends Converter[java.lang.Long, T] {
private var `type`: Class[T] = null
private var em: EntityManager = null
def this(`type`: Class[T], em: EntityManager) {
this()
this.`type` = `type`
this.em = em
}
def convert(key: java.lang.Long): T = {
return em.find(`type`, key)
}
}
最后我不得不在 spring 上下文中注册这些转换器:
<bean id="conversionService"
class="org.springframework.context.support.ConversionServiceFactoryBean">
<property name="converters">
<list>
<bean class="at.granul.spring.jpa.LongToJpaLongIdFactory"/>
<bean class="at.granul.spring.jpa.JpaLongIdToLong"/>
</list>
</property>
</bean>
就是这样!现在很容易定义这种“RealtedTo”风格的关系。
欢迎评论和想法。