Krisztian
Krisztian

Reputation: 477

Field setter not called when list is not empty

I have a parent entity that holds a list of child entities. I'm using Spring Data Rest so there is no custom controller.

These are my entities:

@Entity
class Template(
   childComponents: MutableList<AbstractLabelComponent> = mutableListOf(),
){
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    var id: Long? = null

    @JsonManagedReference
    @OneToMany(mappedBy = "template", cascade = [CascadeType.ALL], orphanRemoval = true)
    private var components: MutableList<AbstractLabelComponent> = childComponents
        set(value){
            field.clear()
            field.addAll(value)
            field.forEach { it.template = this }
        }

    fun addComponent(component: AbstractLabelComponent){
        component.template = this
        this.components.add(component)
     }
}

And the child class:

@Entity
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
@JsonTypeInfo(use=JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "type")
@JsonSubTypes(
    JsonSubTypes.Type(value = TextComponent::class, name = TextComponent.TYPE),
    JsonSubTypes.Type(value = TextAreaComponent::class, name = TextAreaComponent.TYPE),
    JsonSubTypes.Type(value = ImageComponent::class, name = ImageComponent.TYPE)
)
abstract class AbstractLabelComponent(
    
    @field:ManyToOne
    @field:JsonBackReference
    @field:JoinColumn(name="template_id")
    open var template: Template?
){
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    open var id: Long? = null
}

This is the json I'm posting to the API:

{
    "components": [
        {
            "id": 2300,
        },
        {
            "id": 2302,
        }
    ],
    "id": 1789
}

I've left some simple fields out to make it more readable. I have no repository for components and the template repository has no code other than extending the basic crud repo. At first, the child components were created without any problem but the template_id field was not set. This is why I created the setter for the components field to set the template. This works fine when I add components to a template that has no components, however I noticed that when I try to add more of them, they end up having no template ID again.

I've added a breakpoint to the setter and turns out, it is not called. I figured probably because if the list is not empty, JPA is not setting the list but instead adding elements to it. Am I right? If so, is there a way to tell it to use the addComponent method instead so I can set the template? Or any other way to ensure that a reference to the template is set?

Upvotes: 1

Views: 82

Answers (1)

Krisztian
Krisztian

Reputation: 477

Turns out, the difference between the two scenarios was not the number of components present in the database but whether there were any changes to the entity. Not sure but seems like JPA is not persisting the entity if there are no changes and probably it does not bother setting these kind of relationships either. There may be a better solution but the workaround is to set the template id in the JSON from the frontend if the entity is not new.

Upvotes: 0

Related Questions