开发者

Using a composite key in GORM

In section 5.5.2.5 of the grails document it says

GORM supports the concept of composite identifiers (identifiers composed from 2 or more properties). It is not an approach we recommend, but is available to you if you need it

Why isn't it a good idea? I have the fol开发者_StackOverflow社区lowing table definition:

User (Table)
   Column: userId (Primary Key)

FriendMap
   Composite Key Column: userId (foreign key from User) and friendId

Is this a bad idea?


It's not as bad of an idea for join tables used for many-to-many mappings, which is what it looks like you're using it for.

There are a number of arguments against using composite keys instead of using a single, numeric, incrementing id field. They mostly involve making it more complicated to change and refactor your domain.

For mapping classes, a good example to look at is Burt's mapping class between User and Role for the spring-security-core plugin.


I see evidence of why its not recommended. The friendMap class which has the composite key had also "version=false".

Under some cases, I was getting:

org.hibernate.StaleStateException: Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1
        at org.hibernate.jdbc.Expectations$BasicExpectation.checkBatched(Expectations.java:85)
        at org.hibernate.jdbc.Expectations$BasicExpectation.verifyOutcome(Expectations.java:70)
        at org.hibernate.jdbc.BatchingBatcher.checkRowCounts(BatchingBatcher.java:90)
        at org.hibernate.jdbc.BatchingBatcher.doExecuteBatch(BatchingBatcher.java:70)
        at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:268)
        at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:266)
        at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:172)
        at org.codehaus.groovy.grails.orm.hibernate.events.PatchedDefaultFlushEventListener.performExecutions(PatchedDefaultFlush
EventListener.java:46)
        at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:50)
        at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1027)
        at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:365)
        at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:137)

I recently saw this when I was deleting a FriendMap object. This also doesn't happen all the time. I found comments online that this can be an issue with version=false and a composite key. I decided to back to a single, numeric, incrementing id field. Since then, I have not seen any issues. I dont know the entire issue but I wouldn't recommend a composite key with versioning turned off.


I completely disagree with the Grails guys on this one. Composite keys ensure consistency in your database and are necessary in many cases to have a properly normalized database.

See http://weblogs.sqlteam.com/jeffs/archive/2007/08/23/composite_primary_keys.aspx

This is an important basic database modelling concept, and I'm surprised it is glossed over in grails.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜