Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to avoid Hibernate generating two queries for an update with OneToMany?

I'm facing the same situation as in this question, that has no useful answer.

When I add a new element to the many part of my one-to-many relation, Hibernate generates two queries, one to insert and one to update the foreign key to the parent.

Why does it need the second query for? Isn't the parent's id set in the insert? Is there any way of avoiding this?

    Hibernate:
        /* insert mydomain.LanguageKnowledge */
            insert
            into
                languageKnowledge
                (language_fk, level_fk, personId_fk)
            values
                (?, ?, ?)
    Hibernate:
        /* create one-to-many row mydomain.Person.offeredLanguages */
        update
            languageKnowledge
        set
            personId_fk=?
        where
            id=?



    public class LanguageKnowledge {

        @Id
        @GeneratedValue(strategy = IDENTITY)
        private Integer id;

        @Enumerated(STRING)
        @Column(name = "language_fk")
        private LanguageIso639_3 language;

        @Enumerated(STRING)
        @Column(name = "level_fk")
        private LanguageLevel level;

        protected LanguageKnowledge() {
        }
    }


    public class Person {

        @Id
        @GeneratedValue(strategy = IDENTITY)
        private Integer id;

        @OneToMany(fetch = EAGER, cascade = {ALL}, orphanRemoval = true)
        @JoinColumn(name = "personId_fk", referencedColumnName = "id", nullable = false)
        private final Set<LanguageKnowledge> offeredLanguages = new HashSet<>();

        public Person(Set<LanguageKnowledge> offeredLanguages) {
            addOfferedLanguages(offeredLanguages);
        }

        protected Person() {
        }

        public void addOfferedLanguages(Set<LanguageKnowledge> offeredLanguages) {
            this.offeredLanguages.addAll(offeredLanguages);
        }

        public void removeOfferedLanguages(Set<LanguageKnowledge> offeredLanguagesToRemove) {
            this.offeredLanguages.removeAll(offeredLanguagesToRemove);
        }
    }
like image 429
mark951131b Avatar asked Oct 19 '22 16:10

mark951131b


1 Answers

The association is uni-directional, so Person is the owning side (because it's the only side).

Make the association bidirectional and make LanguageKnowledge the association owner. That way you will avoid redundant updates because the foreign key values will be specified as part of insert statements for LanguageKnowledge.

like image 131
Dragan Bozanovic Avatar answered Oct 21 '22 04:10

Dragan Bozanovic