@OneToMany relations in Hibernate and its perils
Tags: hibernate, java, persistence, beginners
Published: 2018-12-02 21:40:11

---
title: @OneToMany relations in Hibernate and its perils
published: true
description: A guide how to persist entities with after digging through several exceptions.
tags: #hibernate #java #persistence #beginners
---

Recently, I had trouble persisting an object with Hibernate. I would like to depict my journey along the well-known example of documenting the microphones of a karaoke bar! Here, we have two microphones (of course, a yellow one to the obligatory black one!) for our bar called Monster Karaoke. We create the microphones first, then the bar and ultimately save it to a corresponding JPA repository.

```java
Microphone blackMicrophone = Microphone.builder()
                .microphoneId(UUID.randomUUID())
                .color("black")
                .build();

Microphone yellowMicrophone = Microphone.builder()
                .microphoneId(UUID.randomUUID())
                .color("yellow")
                .build();

List<Microphone> microphoneList = Arrays.asList(blackMicrophone, yellowMicrophone);

KaraokeBar karaokeBar = KaraokeBar.builder()
                .barId(UUID.randomUUID())
                .name("Monster Karaoke")
                .microphoneList(microphoneList)
                .build();

karaokeBarRepository.save(karaokeBar);
```
A KaraokeBar object contains a list of Microphone objects which is annotated with Hibernate's `@OneToMany`. But when executing the code, following happens:

```java
Request processing failed; 
nested exception is org.springframework.orm.jpa.JpaObjectRetrievalFailureException: 
Unable to find de.schmowser.radio.domain.Microphone with id fb133ab8-72ee-4bf4-ac5f-4701cb99e766;
```
Couldn't be found? I see that we need to cascade persistence such that our magnificiently painted micros get persisted when the KaraokeBar instance is. But even after adding

```java
@OneToMany(cascade = CascadeType.PERSIST)
private List<Microphone> microphoneList;
```
a `javax.persistence.EntityNotFoundException` convinces us that the microphones are still not committed for persistence. And only now, I remember that we know someone who is responsible for persisting any entities to databases. It's the EntityManager within the `@PersistenceContext`. After autowiring it and using entityManager.perist, this pops up:
```
No EntityManager with actual transaction available for current thread - 
cannot reliably process 'persist' call
```
Yeah, we have to annotate the method with `@Transactional` denoting that all transactional matters are handled in the background automatically! Furthermore, we have to define the owner side object (KaraokeBar) first, then setting it in our Microphone instances, and then setting the list in karaokeBar. Otherwise, this exception occurs.
```
org.hibernate.TransientPropertyValueException: 
Not-null property references a transient value - 
transient instance must be saved before current operation : 
de.schmowser.radio.domain.Microphone.karaokeBar -> de.schmowser.radio.domain.KaraokeBar
```
It feels like we are close to letting our customers know which microphones our bar offers. Curiously, without the Repository.save command, the following code snippet compiles...
```java
List<Microphone> microphoneList = Arrays.asList(blackMicrophone, yellowMicrophone);

karaokeBar.setMicrophoneList(microphoneList);

entityManager.persist(karaokeBar);
entityManager.persist(blackMicrophone);
entityManager.persist(yellowMicrophone);

karaokeBarRepository.save(karaokeBar);
```
...while _with_ saving, it does not. Having the last line included rewards us with a `java.lang.UnsupportedOperationException`. This one is actually quite hard to decipher. Somehow, Hibernate neither likes us nor unmodifiable lists. Therefore, we give him what it wants: Something to modify.
```java
List<Microphone> microphoneList = new ArrayList<>();
microphoneList.add(blackMicrophone);
microphoneList.add(yellowMicrophone);
```
Hibernate is merciful and gives us what we desire!
```java
Hibernate: insert into karaoke_bar (name, karaokebar_id) values (?, ?)
Hibernate: insert into microphone (color, karaokebar_id, microphone_id) values (?, ?, ?)
Hibernate: insert into microphone (color, karaokebar_id, microphone_id) values (?, ?, ?)
```
Is this anyway near your experience with Hibernate? How do you handle this storm of exceptions - generally and maybe more effectively?