[hibernate-dev] [OGM] @JoinColumns, @EmbeddedId & IN_ENTITY mode

Guillaume SCHEIBEL guillaume.scheibel at gmail.com
Mon Sep 24 14:20:06 EDT 2012


Hi guys,

I'm working on OGM-236 which consists to use by default the IN_ENTITY mode
for association storage strategy instead of COLLECTION.
I've just found out a little issue, when we use @JoinColumns over a
@OneToMany property to map an @EmbeddedID with the IN_ENTITY mode, the
navigation information are not stored directly into the document itself but
another document composed by the join columns as the _id and the navigation
information (in that case the IDs that the entity is related to).

Concretely, let's starting from this mapping:
https://github.com/hibernate/hibernate-ogm/blob/master/hibernate-ogm-core/src/test/java/org/hibernate/ogm/test/id/Label.java
https://github.com/hibernate/hibernate-ogm/blob/master/hibernate-ogm-core/src/test/java/org/hibernate/ogm/test/id/News.java
https://github.com/hibernate/hibernate-ogm/blob/master/hibernate-ogm-core/src/test/java/org/hibernate/ogm/test/id/NewsID.java

and run this test with the IN_ENTITY mode on (to make the switch, a
modification into MongoDBDatastoreProvider.configure() is needed)
https://github.com/hibernate/hibernate-ogm/blob/master/hibernate-ogm-core/src/test/java/org/hibernate/ogm/test/id/CompositeIdTest.java


We can expect to have something like:

{
    "_id": {
        "author": "Guillaume",
        "title": "There are more than 20 JUGs in France"
    },
   "content": "Great! Congratulations folks",
    "labels": [

        { "id": NumberLong(5) }

]

}

It means this News is related to 1 Label of which ID is 5.
But due to @JoinColumns we got this (both documents are from the News
collection):

{
    "_id": {
        "author": "Guillaume",
        "title": "There are more than 20 JUGs in France"
    },
    "content": "Great! Congratulations folks",
    "labels": []
} {
    "_id": {
        "news_author_fk": "Guillaume",
        "news_topic_fk": "There are more than 20 JUGs in France"
    },
    "labels": [{
        "id": NumberLong(5)
    }]
}

Of course at the loading, when the News seems not related to any Label
because the "labels" field is empty.
A workaround it to change the @JoinColumns from:

@JoinColumns({@JoinColumn(name="news_topic_fk", referencedColumnName =
"newsid.title", nullable = false) ,
	      @JoinColumn(name="news_author_fk", referencedColumnName =
"newsid.author", nullable = false)})
private List<Label> labels;

@JoinColumns({@JoinColumn(name="title", referencedColumnName =
"newsid.title", nullable = false) ,
	      @JoinColumn(name="author", referencedColumnName =
"newsid.author", nullable = false)})
private List<Label> labels;

Note that the new value of each @JoinColumn's name is the same as
referenced property from the @Embedded entity.

I see there are 2 fix possible for this issue:
- we can say in case of IN_ENTITY mode don't use @JoinColumns' name to
store the navigation property but the property from the referenced
column.
- at the loading, we can check also the documents created due to @JoinColumns

Personally, I would tend to the first approach which is more natural
in terms of storage and more readable.

What do you think ?
Let me know if you need more information.

Guillaume


More information about the hibernate-dev mailing list