Home > OS >  How to add new entries to an entity's collection in Springboot
How to add new entries to an entity's collection in Springboot

Time:02-05

Let's say there is a class as follows:

@Data
@AllArgsConstructor
@NoArgsConstructor
@Entity
class OauthUser(
    @OneToMany(cascade = [CascadeType.ALL], fetch = FetchType.EAGER)
    var oauthAttributes: List<OauthAttribute>,

    @NotNull
    @Column(unique = true)
    var email: String,
    var firstName: String,
    var lastName: String
) : OAuth2User {

    @Id
    @NotNull
    @GeneratedValue(strategy = GenerationType.SEQUENCE)
    var id: Long? = null

}

I am trying to add new entries of oauthAttributes when a user logs in again after initially logging in, so that if there is an updated attribute, a new attribute is created to keep a history of profle changes.

I am not able to userRepository.findByEmail(email).oauthAttributes.add(newEntry) because oauthAttributes is defined as a List, which doesn't have the add method. When I try to cast it to ArrayList I get the following error: java.lang.ClassCastException: class org.hibernate.collection.internal.PersistentBag cannot be cast to class java.util.ArrayList.

How can I go about adding an entry into that lits?

CodePudding user response:

After doing some reading and experimenting I found that the following works:

  1. Create a reference to the user in the OauthAttribute class, like so:
    @ManyToOne
    @JoinColumn(name = "user_id")
    @NotNull
    lateinit var user: OauthUser
  1. Adjust the oauthAttributes collection definition in the OauthUser class, from
    @OneToMany(cascade = [CascadeType.ALL], fetch = FetchType.EAGER)
    var oauthAttributes: List<OauthAttribute>,

to

    @OneToMany(cascade = [CascadeType.ALL], fetch = FetchType.EAGER, mappedBy = "user")
    var oauthAttributes: List<OauthAttribute>?

This will create a user_id foreign key reference in the oauth_attribute table instead of a separate join table. Now it is possible to simply create new instances of the OauthAttribute class and assign them to the user by simply specifying assigning the user class property to the corresponding user.

I welcome any comments in case that solution isn't optimal. Also, I believe the question still stands for many to many relationships.

CodePudding user response:

After running into this issue again I've realised that there is something I was missing:

@OneToMany(cascade = [CascadeType.ALL], fetch = FetchType.EAGER)
var oauthAttributes: List<OauthAttribute>,

In Kotlin, List is of a non-mutable type and hence does not contain the method add, nor can it be cast to a mutable collection. In order to achieve what the original question was asking, the field definition needs to be changed to MutableList, like so:

@OneToMany(cascade = [CascadeType.ALL], fetch = FetchType.EAGER)
var oauthAttributes: MutableList<OauthAttribute>,
  • Related