Persisting entities with relations with Hibernate ORM

304 views
Skip to first unread message

Stephane Epardaud

unread,
Mar 30, 2021, 4:32:53 AM3/30/21
to Quarkus Development mailing list
Hi,

In https://stackoverflow.com/questions/66812615/quarkus-panache-1-m-mapping-not-giving-proper-response a user was having trouble sending his entity tree and persisting it, because its relations were not persisted.

Turns out it appears to be due to the relations owning the relation, so if you send an object of type

{
"name":"mango",
"fruits": [
    {"name":"a",
     "color":"red"
    },
    {"name":"b",
     "color":"yellow"
    }
]
}
Where the entities are of this type:

@Entity
public class Tree extends PanacheEntity {
    
    public String name;
    
    @OneToMany(mappedBy = "tree", fetch = FetchType.EAGER, 
cascade = CascadeType.ALL, orphanRemoval = true)
    public List<Fruit> fruits;
}

@Entity
public class Fruit extends PanacheEntity {

    public String name;
    public String color;

    @ManyToOne(fetch = FetchType.EAGER)
    @JoinColumn(name="treeId")
    public Tree tree;
}

Then if your endpoint is:
    @POST
    @Transactional
    public void addTree(Tree tree) {
        Tree.persist(tree);
    }
The Tree is persisted, but not its Fruit instances. And that's because all the Fruit.tree back-refs are not set, and in fact cannot be set, because JSON doesn't support references, so the user needs to add an extra set of setting those back-refs before persisting:
    public void addTree(Tree tree) {
        for(Fruit fruit : tree.fruits)
             fruit.tree = tree;
        Tree.persist(tree);
    }
That's pretty counter-intuitive, even though I guess it's logical, because the Fruit entities are the owning side of the relation, but it must be a common issue. What is the recommended way to deal with this sort of issue?
--

Stéphane Épardaud

Sanne Grinovero

unread,
Mar 30, 2021, 6:41:12 AM3/30/21
to Stef Epardaud, Quarkus Development mailing list

Well this is a huge Pandora box; one of the unsolved fundamental problems of ORM in Java.

Theoretically, Hibernate ORM as the capability to enhance entities for automatic handling of both sides of a relation.

In practice, I've disabled this in Quarkus and wouldn't recommend using it as we figured there's a huge amount of complex implications and unexpected side effects, so I think it's a really bad idea. Having the users explicitly code what they want to happen is the safest bet.

I do agree that people often don't notice and it's a bit confusing. It would be nice if we could detect the inconsistency, but I'm not sure if we can do it safely; it would be tricky to avoid both false positives and false negatives for the same reason we couldn't have it do "the right thing" automatically.

FWIW, this problem only exists among users who insist in detaching complex graphs sourced from external end points and wanting to re-attach a full graph in one go (or persist, like in this example); I know it's popular but I keep saying that it's a bad idea :)  Use a different DTO and code the mapping explicitly, it might look tedious but you're in control and can avoid weird magical side effects; It's also hard to automate as the notion of what is the right thing to do is highly contextual, this really needs explicit user direction.

Last time I was able to dedicate some solid time to this issue my conclusion was that we'd need object relations to be represented by custom collection types (new APIs) which would be more suited to express the relational models. But that's a sad conclusion as it implies you're no longer a pure ORM, as you'd be enforcing the Java object representation rather than allowing people to map standard, untainted POJOs.

This could certainly use some improvements, but be warned it's very tricky.

--
You received this message because you are subscribed to the Google Groups "Quarkus Development mailing list" group.
To unsubscribe from this group and stop receiving emails from it, send an email to quarkus-dev...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/quarkus-dev/CAKU9E9tAj2GGjTkdg-2syp3M5GCTmti2GK1BgYQH%2BWSfrM%2B%3DKg%40mail.gmail.com.

Stephane Epardaud

unread,
Mar 30, 2021, 9:25:53 AM3/30/21
to Sanne Grinovero, Quarkus Development mailing list
Well I'm not sure we need to change anything in Hibernate for that. But this sort of problem (entity/dto) has come up sufficiently often that yeah, I think we should make a move on making it easy to do DTOs and get riid of all those issues once and for all.
--
Stéphane Épardaud
Reply all
Reply to author
Forward
0 new messages