Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
Re: [eclipselink-users] bi-directional mapping causes two inserts

Hello Magnus,

I've filed an EclipseLink bug for the issue:
 https://bugs.eclipse.org/bugs/show_bug.cgi?id=234461

As you've shown, the solution is to not put relationship maintenance code into accessor methods.
Best Regards
Chris

Magnus Heino wrote:

But this works:

        this.building = ModelFixture.createAnonymousBuilding();
        Comment comment = ModelFixture.createComment();
        comment.setBuilding(this.building);

        this.building.addComment(comment);



And then:

    protected void setComments(Set<Comment> comments) {
        this.comments = comments;
    }

    public void addComment(Comment comment) {
        comment.setBuilding(this);
        this.comments.add(comment);
    }

So eclipselink is calling my setter, and is getting confused if I set the building pointer there...

/Magnus

On Wed, May 28, 2008 at 10:22 AM, Magnus Heino <magnus@xxxxxxxxx <mailto:magnus@xxxxxxxxx>> wrote:


    More info...

    This:

            this.building = ModelFixture.createAnonymousBuilding();
            Set<Comment> comments = new HashSet<Comment>();
            Comment comment = ModelFixture.createComment();
            comment.setBuilding(this.building);
            comments.add(comment);

            this.building.setComments(comments);
            this.entityManager.persist(this.building);

    With setComments like this:

    public void setComments(Set<Comment> comments) {
            this.comments = comments;
        }

    works as expected!

    This however:

    this.building = ModelFixture.createAnonymousBuilding();
            Set<Comment> comments = new HashSet<Comment>();
            Comment comment = ModelFixture.createComment();
            comments.add(comment);
            this.building.setComments(comments);
            this.entityManager.persist(this.building);

    With setComments like this:

    public void setComments(Set<Comment> comments) {
            for (Comment comment : comments) {
                comment.setBuilding(this);
            }
            this.comments = comments;
        }

    Fails with double inserts.. what is different? I can't see
    anything special with the debugger.

    I have these properties set:

                    <prop key="eclipselink.logging.level">ALL</prop>
                    <prop
    key="eclipselink.logging.logger">se.lantmateriet.origo.persistence.eclipselink.support.SLF4JSessionLogger</prop>
                    <prop key="eclipselink.logging.timestamp">false</prop>
                    <prop key="eclipselink.logging.thread">false</prop>
                    <prop key="eclipselink.logging.session">true</prop>
                    <prop key="eclipselink.jdbc.native-sql">true</prop>
                    <prop
    key="eclipselink.jdbc.cache-statements">true</prop>
                    <prop key="eclipselink.weaving">false</prop>
                    <prop
    key="eclipselink.ddl-generation">drop-and-create-tables</prop>
                    <prop
    key="eclipselink.ddl-generation.output-mode">both</prop>
                    <prop
    key="eclipselink.application-location">src/main/sql/</prop>

    /Magnus


    On Wed, May 28, 2008 at 8:26 AM, Magnus Heino <magnus@xxxxxxxxx
    <mailto:magnus@xxxxxxxxx>> wrote:

        I added this to Building:

        public Building() {
                try {
                    throw new RuntimeException("debug");
                } catch (RuntimeException e) {
                    this.logger.info
        <http://this.logger.info>("Building created " +
        this.toString(), e);
                }
            }

        and this to Comment:

            @ManyToOne
            @JoinColumn(name = "BUILDING_ID", nullable = false)
            public Building getBuilding() {
                this.logger.debug("Comment " + this.toString() +
        "getBuilding returning " + this.building.toString());
                return this.building;
            }


        and uploaded the output to here:
        http://www.alvkarlebygk.com/eclipselink

        As you can see, Eclipselink is creating many buildings... for
        some reason I don't understand.

        Thanks!

        /Magnus


        On Tue, May 27, 2008 at 9:18 PM, Gordon Yorke
        <gordon.yorke@xxxxxxxxxx <mailto:gordon.yorke@xxxxxxxxxx>> wrote:

            It was also noted that the second Building instance that
            EclipseLink is inserting is different from the one in the
            object.  Are any of the model's getters returning a clone?
            --Gordon

            Gordon Yorke wrote:
            "(insertable=false,updatable=false)" would be a bit of a
            hack.  I expected this to work as mapped and created a
simple test case that confirms this should be working. What else is going on? Is this reproducible in a small
            testcase?
            --Gordon

            Tim Hollosy wrote:
            Magnus,
            I think your @ManyToOne needs a joincolumn annotation like:

            	@ManyToOne
            	@JoinColumn(name="comment_id") //or whatever your join column is

            The other thing to try is setting one side of the relationship to
            readonly (insertable=false,updatable=false).

            Tim

            On Tue, May 27, 2008 at 10:47 AM, Magnus Heino <magnus@xxxxxxxxx> <mailto:magnus@xxxxxxxxx> wrote:
            This is such a basic thing, but I cannot see what I'm doing wrong.

            I have a annotation like this:

            class Building
            @OneToMany(cascade=CascadeType.ALL, mappedBy="building")
            public Set<Comment> getComments() {}

            And then

            class Comment
            @ManyToOne
            public Building getBuilding() {}

            I start a transaction, create a building, add a comment, and call
            entityManager.persist(building);

            Now the INSERT is called twice for the Building. Why? If I remove the
            @ManyToOne and make it unidirectional using a join table, it works.

            I'm using M7.

            Thanks!

            /Magnus


            2008-05-27 16:34:37,792 [main] INFO  Began transaction (1): transaction
            manager [org.springframework.orm.jpa.JpaTransactionManager@11d2066];
            rollback [true] at
            org.springframework.test.context.transaction.TransactionalTestExecutionListener.startNewTransaction(TransactionalTestExecutionListener.java:259)
            2008-05-27 16:34:37,964 [main] TRACE [EL Finest]:
            UnitOfWork(24440876)--Execute query DoesExistQuery() at ?.?(?:?)
            2008-05-27 16:34:37,964 [main] TRACE [EL Finest]:
            UnitOfWork(24440876)--PERSIST operation called on: [Building@51064e objectId
            = 25da2090-9b5e-4b8d-81c3-2197c0ca4e01, objectVersion = 1]. at ?.?(?:?)
            2008-05-27 16:34:37,964 [main] TRACE [EL Finest]:
            ClientSession(30168161)--Execute query ValueReadQuery() at ?.?(?:?)
            2008-05-27 16:34:37,964 [main] DEBUG [EL Fine]:
            ClientSession(30168161)--Connection(6881863)--SELECT id_seq.NEXTVAL FROM
            DUAL at ?.?(?:?)
            2008-05-27 16:34:37,979 [main] TRACE [EL Finest]:
            ServerSession(25218858)--sequencing preallocation for id_seq: objects: 50 ,
            first: 1, last: 50 at ?.?(?:?)
            2008-05-27 16:34:37,979 [main] TRACE [EL Finest]:
            UnitOfWork(24440876)--assign sequence to the object (1 -> [Building@51064e
            objectId = 25da2090-9b5e-4b8d-81c3-2197c0ca4e01, objectVersion = 1]) at
            ?.?(?:?)
            2008-05-27 16:34:37,979 [main] TRACE [EL Finest]:
            UnitOfWork(24440876)--Execute query DoesExistQuery() at ?.?(?:?)
            2008-05-27 16:34:37,979 [main] TRACE [EL Finest]:
            UnitOfWork(24440876)--PERSIST operation called on:
            se.lantmateriet.origo.domain.model.building.Comment@1b3278a. at ?.?(?:?)
            2008-05-27 16:34:37,979 [main] TRACE [EL Finest]:
            UnitOfWork(24440876)--assign sequence to the object (2 ->
            se.lantmateriet.origo.domain.model.building.Comment@1b3278a) at ?.?(?:?)
            2008-05-27 16:34:37,995 [main] TRACE [EL Finest]:
            UnitOfWork(24440876)--Execute query InsertObjectQuery([Building@51064e
            objectId = 25da2090-9b5e-4b8d-81c3-2197c0ca4e01, objectVersion = 1]) at
            ?.?(?:?)
            2008-05-27 16:34:37,995 [main] DEBUG [EL Fine]:
            ClientSession(30168161)--Connection(6881863)--INSERT INTO BUILDING (ID,
            OBJECTID, OBJECTVERSION, VERSION, OBJECTSTATUS, CONSTRUCTIONYEAR,
            HOUSENUMBER, EXTENSIONYEAR, REALPROPERTYKEY, VERSIONVALIDFROM,
            VERSIONVALIDTO, NOADDRESSNEEDED, MAINBUILDING, PREFIX, IDENTITY) VALUES (?,
            ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
                bind => [1, 25da2090-9b5e-4b8d-81c3-2197c0ca4e01, 1, 1, 0, 2008, null,
            null, null, 2008-05-27 16:34:37.979, null, true, true, null, null] at
            ?.?(?:?)
            2008-05-27 16:34:38,026 [main] TRACE [EL Finest]:
            UnitOfWork(24440876)--Execute query
            InsertObjectQuery(se.lantmateriet.origo.domain.model.building.Comment@1b3278a)
            at ?.?(?:?)
            2008-05-27 16:34:38,026 [main] TRACE [EL Finest]:
            UnitOfWork(24440876)--Execute query WriteObjectQuery([Building@24c672
            objectId = 25da2090-9b5e-4b8d-81c3-2197c0ca4e01, objectVersion = 1]) at
            ?.?(?:?)
            2008-05-27 16:34:38,026 [main] DEBUG [EL Fine]:
            ClientSession(30168161)--Connection(6881863)--INSERT INTO BUILDING (ID,
            OBJECTID, OBJECTVERSION, VERSION, OBJECTSTATUS, CONSTRUCTIONYEAR,
            HOUSENUMBER, EXTENSIONYEAR, REALPROPERTYKEY, VERSIONVALIDFROM,
            VERSIONVALIDTO, NOADDRESSNEEDED, MAINBUILDING, PREFIX, IDENTITY) VALUES (?,
            ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
                bind => [1, 25da2090-9b5e-4b8d-81c3-2197c0ca4e01, 1, 1, 0, 2008, null,
            null, null, 2008-05-27 16:34:37.979, null, true, true, null, null] at
            ?.?(?:?)
            2008-05-27 16:34:38,042 [main] DEBUG [EL Fine]:
            ClientSession(30168161)--SELECT 1 FROM DUAL at ?.?(?:?)
            2008-05-27 16:34:38,042 [main] WARN  [EL Warning]:
            UnitOfWork(24440876)--Local Exception Stack:
            Exception [EclipseLink-4002] (Eclipse Persistence Services - 1.0 (Build
            SNAPSHOT - 20080508)): org.eclipse.persistence.exceptions.DatabaseException
            Internal Exception: java.sql.SQLException: ORA-00001: brott mot unik
            begränsning (MAGHEI.SYS_C00135499)

            --

            /Magnus Heino
            _______________________________________________
            eclipselink-users mailing list
            eclipselink-users@xxxxxxxxxxx <mailto:eclipselink-users@xxxxxxxxxxx>
            https://dev.eclipse.org/mailman/listinfo/eclipselink-users


            ------------------------------------------------------------------------
            _______________________________________________
            eclipselink-users mailing list
            eclipselink-users@xxxxxxxxxxx
            <mailto:eclipselink-users@xxxxxxxxxxx>
            https://dev.eclipse.org/mailman/listinfo/eclipselink-users

            _______________________________________________
            eclipselink-users mailing list
            eclipselink-users@xxxxxxxxxxx
            <mailto:eclipselink-users@xxxxxxxxxxx>
            https://dev.eclipse.org/mailman/listinfo/eclipselink-users




-- /Magnus Heino



-- /Magnus Heino



--

/Magnus Heino
------------------------------------------------------------------------

_______________________________________________
eclipselink-users mailing list
eclipselink-users@xxxxxxxxxxx
https://dev.eclipse.org/mailman/listinfo/eclipselink-users


Back to the top