Stephan Stahlmann
Stephan Stahlmann

Reputation: 511

Hibernate initializes collection with immutable list

I have the following entity:

@Entity(name = "courses")
public class Course {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Singular
    @OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
    private Collection<Comment> comments = new ArrayList<>();

    @ManyToOne(fetch = FetchType.LAZY, optional = false)
    private User createdBy;

    public void addComment(Comment comment) {
        comments.add(comment);
    }
}

When I load a course from the database, comments are initialized with a Persistent Bag. The problem occurs when I call addComment(comment), I then get this exception:

Caused by: java.lang.UnsupportedOperationException: null
    at java.base/java.util.AbstractList.add(AbstractList.java:153) ~[na:na]
    at java.base/java.util.AbstractList.add(AbstractList.java:111) ~[na:na]
    at org.hibernate.collection.internal.PersistentBag.add(PersistentBag.java:408) ~[hibernate-core-5.4.18.Final.jar:5.4.18.Final]

It seems that the Persistant Bag, which hibernates assigns, is a Collection.EmptyList, which is immutable and, as such, no comments can be added.

What do I need to change to be able to add comments?

Upvotes: 7

Views: 3461

Answers (1)

Stephan Stahlmann
Stephan Stahlmann

Reputation: 511

Ok so it seems like lombok and hibernate where not really working together as I expected. In addition I had my entity annotated with the following lombok notations:

@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class Course {

    //...
    
    @Singular
    @OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
    private List<Comment> comments = new ArrayList<>();
}

When I loaded an entity from the DB it seems lombok uses the builder pattern to create a new instance. This will result in comment having a Collection.EmptyList assigned and then no new comments can be added since it is immutable. My fix was/is to remove the @Singular and add a @Builder.Default. Now a new ArrayList<>() is assigned instead the immutable list. Now I can't use the created singular builder methods but at least it works.

Upvotes: 5

Related Questions