Changed behavior in cascade after upgrading from hibernate 6.4.1 to 6.4.4

While upgrading Spring Boot from 3.2.2 to 3.2.5, which in turn upgrades hibernate from 6.4.1 to 6.4.4, I encountered a failing test. I can’t seem to find out why.

I have the following two entities (with only the relevant columns):

@Setter
@Entity
@AllArgsConstructor
@NoArgsConstructor
public class ElementOption {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Getter
    private Integer id;

    @ManyToOne
    @NotNull
    private Element element;
}

and

@Entity
@AllArgsConstructor
@NoArgsConstructor
@Getter
@Builder
public class Element {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Setter
    private Integer id;

    @Builder.Default
    @OneToMany(mappedBy = "element", cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER)
    private List<ElementOption> elementOptions = new ArrayList<>();
}

I have a test case that contain the following piece of setup:

        Element element = new Element();
        ElementOption elementOption = new ElementOption();
        elementOption.setElement(element);
        element.getElementOptions().add(elementOption);
        elementRepository.save(element);

        // elementOption.getId() is set prior to 6.4.4

Prior to upgrading, the elementOption would get refreshed (at least that is my interpretation), after the element is saved.

However, now on the hibernate 6.4.4, that is not the case, and I would have to find the new elementOption through the element model. While it is certainly doable, I would like to find out whether I am doing something wrong or if something has changed in hibernate in this regard?

Best regards
Anders

Spring CrudRepository#save method uses the Hibernate merge operation under the hood. This used to previously modify the instance that was passed to it when it had a generated identifier, and that was recently changed to align with the concept that merge should create a copy of the entity instance it was passed and return its persistent state instead of modifying the original one.

You should use the returned element instance like so:

element = elementRepository.save(element);
assert element.getId() != null;

See also the save method’s javadoc: CrudRepository (Spring Data Core 3.2.5 API).

1 Like

Thank you very much! I was convinced that the issue was related to hibernate, and not spring :slight_smile: