Neo4j - OGM在Kotlin中不会抛出任何实体

问题描述 投票:4回答:2

就像上面的瓷砖一样,我一直在尝试使用neo4j-ogm和kotlin而没有成功。如果我试图坚持我的数据,Neo4j会抛出一个异常,“类xxxx不是一个有效的实体”。

package com.asofttz.micros.administrator.users.testmodels

import org.neo4j.ogm.annotation.GeneratedValue
import org.neo4j.ogm.annotation.Id
import org.neo4j.ogm.annotation.NodeEntity
import org.neo4j.ogm.annotation.Relationship

@NodeEntity
class Actor(var name: String = "") {

    @Id
    @GeneratedValue
    open var id: Long? = null

    @Relationship(type = "ACTS_IN", direction = "OUTGOING")
    open val movies = hashSetOf<Movie>()

    fun actsIn(movie: Movie) {
        movies.add(movie)
        movie.actors.plus(this)
    }
}
@NodeEntity
class Movie(var title: String = "", var released: Int = 2000) {

    @Id
    @GeneratedValue
    open var id: Long? = null
    @Relationship(type = "ACTS_IN", direction = "INCOMING")
    open var actors = setOf<Actor>()
}

有办法吗?是否存在使用kotlin将数据保存到Neo4j数据库的替代方法?

N:乙。我使用的是kotlin版本1.2.60和Neo4j-OGM v3.2.1

Update

Below is the rest of my code
import com.asofttz.micros.administrator.users.testmodels.Actor
import com.asofttz.micros.administrator.users.testmodels.Movie
import org.neo4j.ogm.config.Configuration
import org.neo4j.ogm.session.SessionFactory
import java.util.*


object Neo4j {
    val configuration = Configuration.Builder()
            .uri("bolt://localhost")
            .credentials("neo4j", "password")
            .build()

    val sessionFactory = SessionFactory(configuration, "test.movies.domain")

    fun save() {

        val session = sessionFactory.openSession()

        val movie = Movie("The Matrix", 1999)

        session.save(movie)

        val matrix = session.load(Movie::class.java, movie.id)
        for (actor in matrix.actors) {
            println("Actor: " + actor.name)
        }
    }
}

build.gradle文件看起来像这样

apply plugin: 'kotlin'
apply plugin: 'application'
apply plugin: "org.jetbrains.kotlin.plugin.noarg"

repositories {
    jcenter()
    mavenCentral()
    maven { url "http://dl.bintray.com/kotlin/ktor" }
    maven { url "https://dl.bintray.com/kotlin/kontlinx" }
}

noArg {
    annotation("org.neo4j.ogm.annotation.NodeEntity")
    annotation("org.neo4j.ogm.annotation.RelationshipEntity")
}

dependencies {
    compile "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
    compile "io.ktor:ktor:$ktor_version"
    compile "io.ktor:ktor-server-netty:$ktor_version"

    compile project(":asoftlibs:micros:administrator:users:users-jvm")

    compile 'org.neo4j:neo4j-ogm-core:3.1.2'
    compile 'org.neo4j:neo4j-ogm-bolt-driver:3.1.2'
}

kotlin {
    experimental {
        coroutines "enable"
    }
}

compileKotlin {
    kotlinOptions.jvmTarget = "1.8"
}
compileTestKotlin {
    kotlinOptions.jvmTarget = "1.8"
}
sourceCompatibility = "1.8"

我得到了类'com.asofttz.micros.administrator.users.testmodels.Movie不是一个有效的实体',我们将不胜感激。

注意:我还尝试使用no pram构造函数打开电影类,但id ddnt也可以帮助。另一个尝试是改变neo4j-ogm的版本,所以我测试了2.1.5,3.0.1和3.1.2。没有成功

neo4j kotlin neo4j-ogm
2个回答
5
投票

编辑:超简答案没有解释是:在您的示例中,您正在配置错误的类扫描包。你打开与val sessionFactory = SessionFactory(configuration, "test.movies.domain")的会议,但它需要是val sessionFactory = SessionFactory(configuration, "com.asofttz.micros.administrator.users.testmodels")判断你的模型的包声明。但另外,请查看我的更长版本,了解一些最佳做法和解释:

在这里找到完整且有效的例子:Minimal Kotlin/Gradle Example for Neo4j OGM

让我带你走过去:

build.gradle中,将No-arg compiler plugin定义为构建脚本依赖项。

buildscript {
    dependencies {
        classpath "org.jetbrains.kotlin:kotlin-noarg:1.2.51"
    }
}

然后使用noArg块来定义哪些类应该合成无参数构造函数:

noArg {
    annotation("org.neo4j.ogm.annotation.NodeEntity")
    annotation("org.neo4j.ogm.annotation.RelationshipEntity")
}

这意味着:所有使用@NodeEntity@RelationshipEntity注释的类都应该有一个合成的无参数构造函数。

我绝对同意Jasper的说法,这是比默认所有域类的构造函数参数更好的方法,供参考,kotlin-noarg docs:

no-arg编译器插件为具有特定注释的类生成额外的零参数构造函数。

生成的构造函数是合成的,因此不能直接从Java或Kotlin调用,但可以使用反射调用它。

关于域类:Neo4j OGM映射的类不必是最终的。但是我们不支持final字段,因此没有纯粹的不可变类。这就是目前的情况。

所以这里有两个域类:

@NodeEntity
class Actor(var name: String) {

    @Id
    @GeneratedValue
    var id: Long? = null

    @Relationship(type = "ACTS_IN", direction = "OUTGOING")
    var movies = mutableSetOf<Movie>()

    fun actsIn(movie: Movie) {
        movies.add(movie)
        movie.actors.add(this)
    }
}

@NodeEntity
class Movie(var title: String, var released: Int) {

    @Id
    @GeneratedValue
    var id: Long? = null
    @Relationship(type = "ACTS_IN", direction = "INCOMING")
    var actors = mutableSetOf<Actor>()
}

请注意,所有字段都是var,而不是val。您可以在此安全地省略open关键字。另请注意,我确实删除了“真实”商业信息的默认参数(此处为标题和发行年份)。

我们必须特别注意这些集合:我删除了明确的hashSetOf,而是使用mutableSetOf。我们可以使用#add来改变集合本身。

如果您更喜欢Kotlin惯用法,请使用setOf并利用我们的属性不再是final的事实并改变字段本身:

@NodeEntity
class Actor(var name: String) {

    @Id
    @GeneratedValue
    var id: Long? = null

    @Relationship(type = "ACTS_IN", direction = "OUTGOING")
    var movies = setOf<Movie>()

    fun actsIn(movie: Movie) {
        movies += movie
        movie.actors += this
    }
}

@NodeEntity
class Movie(var title: String, var released: Int) {

    @Id
    @GeneratedValue
    var id: Long? = null
    @Relationship(type = "ACTS_IN", direction = "INCOMING")
    var actors = setOf<Actor>()
}

请注意:在您的原始示例中,您有一个类似movie.actors.plus(this)的声明。这不会改变集合但会创建一个新集合,就像集合的+运算符一样。

在建模层面:我个人不会在两个方向上映射关系。这往往会让你迟早咬你,就像它在JPA / ORM世界中一样。映射逻辑所需的方向,并分别对路径等执行其他查询。

请让我知道这可不可以帮你。我正在关闭你现在创建的GH问题。


2
投票

OGM要求类是开放的并且具有无参数构造函数。 Java中的类默认显示这些特征,但它们不在Kotlin中。

您可以将类标记为打开,并手动添加默认构造函数,也可以使用'no-args'和'kotlin-spring'gradle插件。这是一个使用Kotlin,Spring Data SDN和OGM的sample application。请注意我们在构建文件中:

noArg {
    annotation("org.neo4j.ogm.annotation.NodeEntity")
    annotation("org.neo4j.ogm.annotation.RelationshipEntity")
    annotation("org.springframework.data.neo4j.annotation.QueryResult")
}

这与手动添加默认构造函数相同,但是:

  • 代码更清晰
  • 默认构造函数专门用于在运行时使用的lib,否则将被隐藏。

作为替代方案,您可以使用螺栓驱动程序并手动映射查询结果。当您对特定用例进行自定义查询时,这是一个很好的选择 - 例如具有高流量和仔细调整查询的应用程序。

这是一个sample application显示使用螺栓驱动器directly

热门问题
推荐问题
最新问题