eBook – Guide Spring Cloud – NPI EA (cat=Spring Cloud)
announcement - icon

Let's get started with a Microservice Architecture with Spring Cloud:

>> Join Pro and download the eBook

eBook – Mockito – NPI EA (tag = Mockito)
announcement - icon

Mocking is an essential part of unit testing, and the Mockito library makes it easy to write clean and intuitive unit tests for your Java code.

Get started with mocking and improve your application tests using our Mockito guide:

Download the eBook

eBook – Java Concurrency – NPI EA (cat=Java Concurrency)
announcement - icon

Handling concurrency in an application can be a tricky process with many potential pitfalls. A solid grasp of the fundamentals will go a long way to help minimize these issues.

Get started with understanding multi-threaded applications with our Java Concurrency guide:

>> Download the eBook

eBook – Reactive – NPI EA (cat=Reactive)
announcement - icon

Spring 5 added support for reactive programming with the Spring WebFlux module, which has been improved upon ever since. Get started with the Reactor project basics and reactive programming in Spring Boot:

>> Join Pro and download the eBook

eBook – Java Streams – NPI EA (cat=Java Streams)
announcement - icon

Since its introduction in Java 8, the Stream API has become a staple of Java development. The basic operations like iterating, filtering, mapping sequences of elements are deceptively simple to use.

But these can also be overused and fall into some common pitfalls.

To get a better understanding on how Streams work and how to combine them with other language features, check out our guide to Java Streams:

>> Join Pro and download the eBook

eBook – Jackson – NPI EA (cat=Jackson)
announcement - icon

Do JSON right with Jackson

Download the E-book

eBook – HTTP Client – NPI EA (cat=Http Client-Side)
announcement - icon

Get the most out of the Apache HTTP Client

Download the E-book

eBook – Maven – NPI EA (cat = Maven)
announcement - icon

Get Started with Apache Maven:

Download the E-book

eBook – Persistence – NPI EA (cat=Persistence)
announcement - icon

Working on getting your persistence layer right with Spring?

Explore the eBook

eBook – RwS – NPI EA (cat=Spring MVC)
announcement - icon

Building a REST API with Spring?

Download the E-book

Course – LS – NPI EA (cat=Jackson)
announcement - icon

Get started with Spring and Spring Boot, through the Learn Spring course:

>> LEARN SPRING
Course – RWSB – NPI EA (cat=REST)
announcement - icon

Explore Spring Boot 3 and Spring 6 in-depth through building a full REST API with the framework:

>> The New “REST With Spring Boot”

Course – LSS – NPI EA (cat=Spring Security)
announcement - icon

Yes, Spring Security can be complex, from the more advanced functionality within the Core to the deep OAuth support in the framework.

I built the security material as two full courses - Core and OAuth, to get practical with these more complex scenarios. We explore when and how to use each feature and code through it on the backing project.

You can explore the course here:

>> Learn Spring Security

Course – LSD – NPI EA (tag=Spring Data JPA)
announcement - icon

Spring Data JPA is a great way to handle the complexity of JPA with the powerful simplicity of Spring Boot.

Get started with Spring Data JPA through the guided reference course:

>> CHECK OUT THE COURSE

Partner – Moderne – NPI EA (cat=Spring Boot)
announcement - icon

Refactor Java code safely — and automatically — with OpenRewrite.

Refactoring big codebases by hand is slow, risky, and easy to put off. That’s where OpenRewrite comes in. The open-source framework for large-scale, automated code transformations helps teams modernize safely and consistently.

Each month, the creators and maintainers of OpenRewrite at Moderne run live, hands-on training sessions — one for newcomers and one for experienced users. You’ll see how recipes work, how to apply them across projects, and how to modernize code with confidence.

Join the next session, bring your questions, and learn how to automate the kind of work that usually eats your sprint time.

1. Introduction

When we map entity relationships with Hibernate, a small mistake in a field declaration can prevent our application from booting up. A common example is the “org.hibernate.AnnotationException: Illegal attempt to map a non collection as a @OneToMany, @ManyToMany or @CollectionOfElements” error.

In this tutorial, we’ll look at why Hibernate throws this exception. Next, we’ll reproduce it with a simple mapping and walk through a couple of ways to fix it.

2. Understanding the Exception

Hibernate expects any field annotated with @OneToMany, @ManyToMany or @ElementCollection to be a collection-valued association. In practice, this means we must declare the field using one of the collection interfaces it recognizes:

  • Collection or List: an ordered group that allows duplicate elements
  • Set: a group that contains only unique elements
  • Map: a set of key-value pairs, useful for associations based on keys

The reason for this requirement is that Hibernate manages these collections with its own implementation. When we persist an entity, Hibernate replaces that field value with a proxy that supports lazy loading and dirty checking. It can only do that if the field type is an interface it controls.

As such, when the annotation is used on a field that isn’t one of these interfaces, Hibernate can’t build that proxy. Therefore, it fails fast during startup and throws the AnnotationException.

3. Reproducing the Exception

Let’s reproduce the problem with a classic parent-child mapping. First, let’s define a Comment entity:

@Entity
public class Comment {
    @Id
    @GeneratedValue
    private Long id;
    private String text;

    // getters and setters
}

Now, let’s create a Post entity that owns many comments. Here, purposely declare the field with the concrete ArrayList type:

@Entity
public class Post {
    @Id
    @GeneratedValue
    private Long id;

    @OneToMany
    private ArrayList<Comment> comments = new ArrayList<>();

    // getters and setters
}

When Hibernate scans this mapping during building of the metadata at startup, it throws: org.hibernate.AnnotationException: Illegal attempt to map a non collection as a @OneToMany, @ManyToMany or @CollectionOfElements: com.baeldung.Post.comments

Note that newer Hibernate versions phrase the same message with @ElementCollection instead of the legacy @CollectionOfElements, but the cause is identical.

Even though ArrayList is technically a list, Hibernate rejects it because it’s a concrete class rather than a collection interface.

4. Fixing the Mapping

The fix is straightforward: we declare the field using a collection interface instead of the implementation. So, let’s change the type from ArrayList to List:
@Entity
public class Post {
    @Id
    @GeneratedValue
    private Long id;

    @OneToMany
    private List<Comment> comments = new ArrayList<>();

    // getters and setters
}

We should notice that we still initialize the field with new ArrayList<>(). That’s not a problem, because only the type of the declared field needs to be an interface. Hibernate will switch the value for its own implementation once the entity becomes managed.

We can apply the same rule to the other annotations. For instance, a Set pairs well with @ManyToMany when we want to avoid duplicates. @ElementCollection accepts any of the standard collection interfaces. The thing to remember is that the compile time type of the field must be an interface, not the class we assign to it.

Now, when it comes to which interface to pick, a List is the common default when order or duplicates matter, while a Set is a good fit when each element must be unique. Either way, the mapping stays valid as long as the field type remains an interface.

We can encounter the same exception when we place a collection annotation on a single-valued field. For instance, a comment belongs to exactly one post, so we might mistakenly write:

@Entity
public class Comment {
    @Id
    @GeneratedValue
    private Long id;

    @OneToMany
    private Post post;
}

In this case, post holds a single Post, not a collection, so Hibernate throws the same AnnotationException. However, in this case, switching to an interface type won’t help, since the relationship itself is incorrectly modeled.

Instead, we should choose the annotation that matches the cardinality. Considering that many comments map to a single post, @ManyToOne is the correct choice:

@Entity
public class Comment {
    @Id
    @GeneratedValue
    private Long id;

    @ManyToOne
    private Post post;
}

Similarly, if the field represents a one-to-one association, we’d choose @OneToOne instead.

This also ties together the two fixes we’ve seen. In a bidirectional relationship, the @ManyToOne side is the owner of the association, while the Post entity maps the inverse side with @OneToMany(mappedBy = “post”). Here, the @OneToMany field is still a List, and the @ManyToOne field is still a single reference. As such, each annotation matches the type it is assigned to and Hibernate build the mapping without complaints.

6. Conclusion

In this article, we’ve looked at the Hibernate AnnotationException that warns us about mapping an improper type.

The root of the problem is a mismatch between an annotation and a field type. When we use @OneToMany, @ManyToMany, or @ElementCollection, the field must be a collection interface like List or Set, and not a concrete class such as ArrayList. And when the field actually holds a single reference, we should reach for @ManyToOne or @OneToOne instead.

By matching the annotation to the field’s cardinality and always declaring collections through their interface, we keep our mappings valid and let Hibernate deal with their management.

As always, the code is available over on Github.

Baeldung Pro – NPI EA (cat = Baeldung)
announcement - icon

Baeldung Pro comes with both absolutely No-Ads as well as finally with Dark Mode, for a clean learning experience:

>> Explore a clean Baeldung

Once the early-adopter seats are all used, the price will go up and stay at $33/year.

eBook – HTTP Client – NPI EA (cat=HTTP Client-Side)
announcement - icon

The Apache HTTP Client is a very robust library, suitable for both simple and advanced use cases when testing HTTP endpoints. Check out our guide covering basic request and response handling, as well as security, cookies, timeouts, and more:

>> Download the eBook

eBook – Java Concurrency – NPI EA (cat=Java Concurrency)
announcement - icon

Handling concurrency in an application can be a tricky process with many potential pitfalls. A solid grasp of the fundamentals will go a long way to help minimize these issues.

Get started with understanding multi-threaded applications with our Java Concurrency guide:

>> Download the eBook

eBook – Java Streams – NPI EA (cat=Java Streams)
announcement - icon

Since its introduction in Java 8, the Stream API has become a staple of Java development. The basic operations like iterating, filtering, mapping sequences of elements are deceptively simple to use.

But these can also be overused and fall into some common pitfalls.

To get a better understanding on how Streams work and how to combine them with other language features, check out our guide to Java Streams:

>> Join Pro and download the eBook

eBook – Persistence – NPI EA (cat=Persistence)
announcement - icon

Working on getting your persistence layer right with Spring?

Explore the eBook

Course – LS – NPI EA (cat=REST)

announcement - icon

Get started with Spring Boot and with core Spring, through the Learn Spring course:

>> CHECK OUT THE COURSE

Partner – Moderne – NPI EA (tag=Refactoring)
announcement - icon

Modern Java teams move fast — but codebases don’t always keep up. Frameworks change, dependencies drift, and tech debt builds until it starts to drag on delivery. OpenRewrite was built to fix that: an open-source refactoring engine that automates repetitive code changes while keeping developer intent intact.

The monthly training series, led by the creators and maintainers of OpenRewrite at Moderne, walks through real-world migrations and modernization patterns. Whether you’re new to recipes or ready to write your own, you’ll learn practical ways to refactor safely and at scale.

If you’ve ever wished refactoring felt as natural — and as fast — as writing code, this is a good place to start.

Course – Summer Sale 2026 – NPI EA (cat= Baeldung)
announcement - icon

Yes, we're now running our only Summer Sale. All Courses are 30% off until 20th July, 2026:

>> EXPLORE ACCESS NOW

Course – Summer Sale 2026 – NPI (All)
announcement - icon

Yes, we're now running our only Summer Sale. All Courses are 30% off until 20th July, 2026:

>> EXPLORE ACCESS NOW

eBook Jackson – NPI EA – 3 (cat = Jackson)
guest
0 Comments
Oldest
Newest
Inline Feedbacks
View all comments