I'm using micronaut-data-hibernate-jpa and I have one-to-many relation Parent-Children. I'm trying to save parent entity with list of children by save operation on parent repository. Parent and children are saved but child don't have parent id saved in database.
My Entities are defined like this:
import java.util.*
import javax.persistence.*
@Entity
data class Parent(
@Id
@GeneratedValue
var id: UUID? = null,
var name: String,
@OneToMany(mappedBy = "parent",cascade = [CascadeType.ALL])
var children: List<Child> = listOf(),
)
@Entity
data class Child(
@Id
@GeneratedValue
var id: UUID? = null,
var name: String = "",
@ManyToOne(fetch = FetchType.EAGER, cascade = [CascadeType.ALL])
var parent: Parent? = null,
)
Repositories are created using CrudRepository
import io.micronaut.data.annotation.Repository
import io.micronaut.data.repository.CrudRepository
import java.util.*
@Repository
interface ParentRepository : CrudRepository<Parent, UUID>
@Repository
interface ChildRepository : CrudRepository<Child, UUID>
I was using simple test to check if my set up is fine but apparently there is issue
import io.micronaut.test.extensions.junit5.annotation.MicronautTest
import org.junit.jupiter.api.AfterEach
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Assertions.assertNotNull
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
@MicronautTest
class OneToManyTest(
private val parentRepository: ParentRepository,
private val childRepository: ChildRepository,
) {
@BeforeEach
fun setUp() {
val childA = Child(name = "Child A")
val childB = Child(name = "Child B")
val parentOne = Parent(name = "Parent 1", children = listOf(childA, childB))
parentRepository.save(parentOne)
val parentTwo = Parent(name = "Parent 2")
val childC = Child(name = "Child C", parent = parentTwo)
childRepository.save(childC)
}
@AfterEach
fun clean() {
childRepository.deleteAll()
parentRepository.deleteAll()
}
@Test //THIS TEST FAILS
fun `Parent should have child when saved by parent`() {
val actual = parentRepository.findAll().toList().filter { it.name == "Parent 1" }[0]
assertEquals(2, actual.children.size)
}
@Test //THIS TEST FAILS
fun `Child should have parent when saved by parent`() {
val actual = childRepository.findAll().toList().filter { it.name != "Child C" }
assertEquals(2, actual.size) // THIS ASSERT IS OK
assertNotNull(actual[0].parent)
assertNotNull(actual[1].parent)
}
@Test //THIS TEST IS FINE
fun `Parent should have child when saved by child`() {
val actual = parentRepository.findAll().toList().filter { it.name == "Parent 2" }[0]
assertEquals(1, actual.children.size)
}
@Test //THIS TEST IS FINE
fun `Child should have parent when saved by child`() {
val actual = childRepository.findAll().toList().filter { it.name == "Child C" }[0]
assertNotNull(actual.parent)
}
}
I don't know if this is relevant but I use Flyway to generate tables and I'm using postgres
My migration script:
CREATE
EXTENSION IF NOT EXISTS "uuid-ossp";
CREATE TABLE parent
(
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY,
name CHARACTER VARYING NOT NULL
);
CREATE TABLE child
(
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY,
name CHARACTER VARYING NOT NULL,
parent_id UUID REFERENCES parent (id)
)
CodePudding user response:
You declared mappedBy
which defines who is the owner of the relationship, and in your case it’s Child, so you should have the parent assigned there.