1

I have a structure, which (simplified) looks like this:

@NodeEntity(label = "Entity")
class FullEntity {

    @Id @GeneratedValue
    var _id: Long? = null

    @Id @Index(unique = true)
    lateinit var uuid: String

    lateinit var someMoreData: String // this data is sometimes lost

    @Relationship(type = "TARGETS", direction = Relationship.OUTGOING)
    var target: StubEntity? = null
}

@NodeEntity(label = "Entity")
class StubEntity {

    @Id @GeneratedValue
    var _id: Long? = null

    @Id @Index(unique = true)
    lateinit var uuid: String
}

@RepositoryRestResource
interface EntityRepository : Neo4jRepository<FullEntity, Long>

Now when I save two related FullEntity objects independently, it all works if I do it one way:

entityRepository.save(FullEntity().apply {
    uuid = "uuid1"
    someMoreData = "SomeMoreData1"
    target = StubEntity().apply {
        uuid = "uuid2"
    }
})
// some time later ...
entityRepository.save(FullEntity().apply {
    uuid = "uuid2"
    someMoreData = "SomeMoreData2"
})

but if I reverse the order like so:

entityRepository.save(FullEntity().apply {
    uuid = "uuid2"
    someMoreData = "SomeMoreData2"
})
// some time later ...
entityRepository.save(FullEntity().apply {
    uuid = "uuid1"
    someMoreData = "SomeMoreData1"
    target = StubEntity().apply {
        uuid = "uuid2"
    }
})

it removes "SomeMoreData2".

MaciejGórski
  • 22,187
  • 7
  • 70
  • 94
  • 1
    I can somehow reproduce your problem but need some time to analyse. One thing I noticed is that if you would activate indexes, it won't create the entries since you want uniqueness of the uuid for the `Entity` labeled notes. But you also may help me understanding your use case: Why are you defining multiple `Id` fields? – meistermeier Feb 06 '18 at 21:20
  • @meistermeier I actually have unique constraint (and index too) on this `uuid`. `_id` is internal id in Neo database, which I don't really use anywhere. – MaciejGórski Feb 07 '18 at 09:46

1 Answers1

0

I see two problems with your classes and the use in OGM:

  1. You use the label Entity twice. This will create problems if OGM tries to load the data from Neo4j. It cannot find the right type to assign the values. Possible workarounds:

    • Explicitly set the label to another one like StubEntity for this class.

    • If this is not possible because the uniqueness of the uuid over both classes, you may not even need the StubEntity but use the FullEntity class also for the relationship target. There will be no difference in Neo4j after saving the data.

    • If both classes have more differences than the sample code above shows, you may create an abstract class with the Entity label and also provide special type labels (implicit by just annotating with @NodeEntity or explicit with the label attribute you are already using) on the implementing classes. Than you could use the uuid constraint in the abstract class.

  2. Using the @Id annotation twice. There is no need to declare an additional @Id on the uuid field if you just need the field in the index and an unique constraint (if I have understood your comment correct).

meistermeier
  • 7,942
  • 2
  • 36
  • 45