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

Support for Kotlin's value class as document's @Id #4078

Open
gavvvr opened this issue Jun 5, 2022 · 2 comments
Open

Support for Kotlin's value class as document's @Id #4078

gavvvr opened this issue Jun 5, 2022 · 2 comments
Labels
type: enhancement A general enhancement

Comments

@gavvvr
Copy link
Contributor

gavvvr commented Jun 5, 2022

Hi. I think it's a good idea to use Kotlin's inline class to enforce a restriction at the compile time and prevent yourself from mixing up an id of one entity with id on another entity.

Usually the document class looks like this:

@Document
data class Person(@Id var id: String? = null, val name: String)

And you can pass any String to repo's findById method.
I would like to use an inline class for @Id as follows:

@JvmInline
value class PersonId(val value: String)

@Document
data class Person(@Id var id: PersonId? = null, val name: String)

The problem is that it's not fully supported. The repository's save operation works fine (as far as I can see by inspecting my local Mongo instance), but, for example, findAll and findByIdOrNull fail to act as expected in different manners.

Below is an example source code, which can be put into a single test file of a project scaffolded with start.spring.io:

import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Nested
import org.junit.jupiter.api.Test
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.autoconfigure.data.mongo.DataMongoTest
import org.springframework.data.annotation.Id
import org.springframework.data.mongodb.core.mapping.Document
import org.springframework.data.mongodb.repository.MongoRepository
import org.springframework.data.repository.findByIdOrNull
import org.springframework.stereotype.Repository

@JvmInline
value class PersonId(val value: String)

@Document
data class Person(@Id var id: PersonId? = null, val name: String)

@Repository
interface PersonRepository : MongoRepository<Person, PersonId>

@DataMongoTest
class PersonRepositoryTest(@Autowired private val repo: PersonRepository) {

    @Test
    fun `successfully saves person`() {
        val newPerson = Person(name = "Bob")
        val savedPerson = repo.insert(newPerson)
        assertThat(savedPerson.id).isNotNull
    }

    @Nested
    inner class WhenPersonSavedToRepository {

        private var id: PersonId? = null

        @BeforeEach
        fun persistNewPerson() {
            val newPerson = Person(name = "Bob")
            val savedPerson = repo.save(newPerson)
            id = savedPerson.id
        }

        @Test
        fun `finds all persons in the repository (unfortunately throws MappingException)`() {
            val all = repo.findAll()
            assertThat(all).isNotEmpty
        }

        @Test
        fun `finds person by id (unfortunately returns nothing)`() {
            val found = repo.findByIdOrNull(id!!)
            assertThat(found).isNotNull
        }
    }
}
@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged label Jun 5, 2022
@mp911de mp911de added the status: blocked An issue that's blocked on an external project change label Jun 14, 2022
@mp911de
Copy link
Member

mp911de commented Jun 14, 2022

Depends on spring-projects/spring-data-commons#1947

@mp911de mp911de added type: enhancement A general enhancement and removed status: waiting-for-triage An issue we've not yet triaged labels Jun 14, 2022
@jrosn
Copy link

jrosn commented Nov 9, 2024

spring-projects/spring-data-commons#1947 is closed now.
I have the same problem.
Thanks

@mp911de mp911de removed the status: blocked An issue that's blocked on an external project change label Nov 11, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: enhancement A general enhancement
Projects
None yet
Development

No branches or pull requests

4 participants