Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to declare @Id in interface? #54

Closed
ghost opened this issue Feb 11, 2018 · 3 comments
Closed

How to declare @Id in interface? #54

ghost opened this issue Feb 11, 2018 · 3 comments

Comments

@ghost
Copy link

ghost commented Feb 11, 2018

Interface:

@JsonTypeInfo(
        use = JsonTypeInfo.Id.NAME,
        include = JsonTypeInfo.As.PROPERTY,
        property = "type")
@JsonSubTypes(
        value = [
            JsonSubTypes.Type(CaoHistoryRecordNotification::class, name = "history-record-notification")
        ]
)
@Indices(value = arrayOf(
        Index(value = "caObjectLocalId", type = IndexType.NonUnique),
        Index(value = "checked", type = IndexType.NonUnique)
))
interface CaoNotification {
    @Id val localId: UUID
    val caObjectLocalId: UUID
    val checked: Boolean
    val dateTime: LocalDateTime
    val importance: CaoNotificationImportance
}

Data class:

data class CaoHistoryRecordNotification(
        override val localId: UUID,
        override val caObjectLocalId: UUID,
        override val checked: Boolean,
        override val dateTime: LocalDateTime,
        override val importance: CaoNotificationImportance,
        val localCaoHistoryRecordId: UUID
) : CaoNotification

But there is a problem, @Id annotation must be applied to fields only. How can I overcome it?
image

Without such annotation, Nitrite can't find id field for object when I trying to update repo

private val repository = nitrite.getRepository(CaoNotification::class.java)

Or repository of interfaces isn't supported?

@ghost ghost changed the title How to declare @Id in interface How to declare @Id in interface? Feb 11, 2018
@anidotnet
Copy link
Contributor

There is no equivalent of AnnotationTarget.PROPERTY in java. So @Id annotation can not be applied to any abstract property. Repository of interfaces is not supported in Nitrite, as in java there is no way to extract information about abstract property for index/id field validation.

The ideal way to do it as follows:

@JsonTypeInfo(
        use = JsonTypeInfo.Id.NAME,
        include = JsonTypeInfo.As.PROPERTY,
        property = "type")
@JsonSubTypes(
        value = [
            JsonSubTypes.Type(CaoHistoryRecordNotification::class, name = "history-record-notification")
        ]
)
@Indices(value = [(Index(value = "caObjectLocalId", type = IndexType.NonUnique)),
    (Index(value = "checked", type = IndexType.NonUnique))])
interface CaoNotification {
    val localId: UUID
    val caObjectLocalId: UUID
    val checked: Boolean
    val dateTime: LocalDateTime
    val importance: CaoNotificationImportance
}

@InheritIndices
data class CaoHistoryRecordNotification(
        @Id override val localId: UUID,
        override val caObjectLocalId: UUID,
        override val checked: Boolean,
        override val dateTime: LocalDateTime,
        override val importance: CaoNotificationImportance,
        val localCaoHistoryRecordId: UUID
) : CaoNotification

private val repository = nitrite.getRepository<CaoHistoryRecordNotification>()

See issue #37 for @InheritIndices.

@anidotnet anidotnet self-assigned this Feb 11, 2018
@anidotnet anidotnet added this to the 2.2.0 milestone Feb 11, 2018
@anidotnet anidotnet added this to To Do in Nitrite Development via automation Feb 11, 2018
anidotnet added a commit that referenced this issue Feb 11, 2018
@ghost
Copy link
Author

ghost commented Feb 11, 2018

Thanks for quick reply!

But what If I have multiple data classes extending CaoNotification?
In last Kotlin versions, we can extend data classes from abstract/open classes.
Is this the best solution for now?

anidotnet added a commit that referenced this issue Feb 11, 2018
@anidotnet
Copy link
Contributor

Yes you can not create repository of interfaces. You can have a repository of abstract class. But remember all index fields and id fields can not be abstract in that class. Here is an example which I have added in the test cases also

interface MyInterface {
    val id: UUID
}

@Indices(value = [(Index(value = "name", type = IndexType.NonUnique))])
abstract class SomeAbsClass (
        @Id override val id: UUID = UUID.randomUUID(),
        open val name: String = "abcd"
) : MyInterface {
    abstract val checked: Boolean
}

@InheritIndices
class MyClass(
        override val id: UUID,
        override val name: String,
        override val checked: Boolean) : SomeAbsClass(id, name)

@InheritIndices
class MyClass2(
        override val id: UUID,
        override val name: String,
        override val checked: Boolean,
        val importance: Int
) : SomeAbsClass(id, name)

@Test
fun testIssue54() {
        val repository = db?.getRepository<SomeAbsClass>()!!
        assertTrue(repository.hasIndex("id"))
        assertTrue(repository.hasIndex("name"))

        val item = MyClass(UUID.randomUUID(), "xyz", true)
        var writeResult = repository.insert(item)
        assertEquals(writeResult.affectedCount, 1)

        var cursor = repository.find()
        assertEquals(cursor.size(), 1)

        val item2 = MyClass2(UUID.randomUUID(), "123", true, 3)
        writeResult = repository.insert(item2)
        assertEquals(writeResult.affectedCount, 1)

        cursor = repository.find()
        assertEquals(cursor.size(), 2)
}

Nitrite Development automation moved this from To Do to Done Feb 11, 2018
anidotnet added a commit that referenced this issue Feb 12, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Development

No branches or pull requests

1 participant