These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 6 posts ] 
Author Message
 Post subject: Instance identifiers
PostPosted: Fri Jul 01, 2005 9:16 am 
Beginner
Beginner

Joined: Thu Mar 18, 2004 8:11 am
Posts: 38
Location: Italy
Dears,

I'm trying to adopt hibernate for a small project of mine. The project is based on a (PostgreSQL) database in which ids with business-meaning are quite common.

I know that somebody (many?) assert that it is better to have immutable objects ids instead of ones borrowing any business-meaning. I always relegated this statement more to a matter of taste and flavors than to a necessity, even due to the fact that there are counter-arguments to it.

This said, I simply tought that Hibernate wouldn't enforce its own flavor about it, describing itself as a generic "Relational Persistence For Idiomatic Java", not a pattern platform.

I was wrong: when I try to modify any persisted identifier (declared as "assigned", of course), I get the (now) well-know-exception:

"identifier of an instance of ... altered from ... to ...

Is there any way (apart the trivial one of yielding "immutability" to the instance id) to avoid this? Why should I get my db redundant by adding a sequential/identity id to every and each of my db tables?

Regards,

_________________
Giampaolo Tomassoni
Italy


Top
 Profile  
 
 Post subject:
PostPosted: Fri Jul 01, 2005 10:34 am 
Senior
Senior

Joined: Tue Jun 21, 2005 10:18 am
Posts: 135
Location: South Carolina, USA
Quote:
Why should I get my db redundant by adding a sequential/identity id to every and each of my db tables?

Given the way you've written your entry, I'm assuming this question was rhetorical, and you don't wish to argue the advantages/disadvantages of surrogate keys.

However, as for your other questions, while hibernate does (for the most part) support keys with "business meaning" (generally referred to in hibernate documentation as "natural keys"), I do not think it supports mutable IDs, no. To the best of my knowledge, very few ORM/persistence solutions will handle a change in the id for an entity well. Certainly EJB does not.

You may be able to abstract some of your persistence code with something like iBATIS, but even there, it might be kinda touchy. Of course, you're not completely locked out. Direct JDBC should be able to give you what you need, although it won't be much fun to write ;).


Top
 Profile  
 
 Post subject:
PostPosted: Fri Jul 01, 2005 10:35 am 
Regular
Regular

Joined: Sun May 08, 2005 2:48 am
Posts: 118
Location: United Kingdom
The primary-key is the instance identifier.

You can use ids with business meaning if once the object/thing is instanted they never change. The objectives of both never overlap so its safe to compact persistant storage space this way.


However if in the lifecycle of the same object/thiny If you want to change the id because the business meaning has changed, then you have conflicting goals.


Goal 1) Your thingy/object needs an immutable reference for the lifetime of the item.

Goal 2) Your business meaning wants to track some state change.


In this case it makes sense to seperate the fields containing the two distinctly different pieces of information with different purposes.


If you REALLY REALLY want to "move" the primary key, then you have to:

1) Create the same instance at the new primary key id.
2) Update all references to the old value across your entire database schema.
3) Delete the old instance at the old id.

In most cases if your items 2 does not exist (there is no data pointing at it) then the only performance loss you will encounter will be cache miss/reload and the fact that within the Java language any equality operators will not detect its the same instance (f there are other threads with references to the old one), although conceptually you know it is.

But generally the whole idea is usually broken design, you make your own bed of nails trying to combine the two.


Top
 Profile  
 
 Post subject:
PostPosted: Fri Jul 01, 2005 4:01 pm 
Beginner
Beginner

Joined: Thu Mar 18, 2004 8:11 am
Posts: 38
Location: Italy
dlmiles wrote:
The primary-key is the instance identifier.

You can use ids with business meaning if once the object/thing is instanted they never change. The objectives of both never overlap so its safe to compact persistant storage space this way.


Thank you for your reply: it lets me understand why hibernate behaves this way. It is to comply with EJB specs.


Quote:
However if in the lifecycle of the same object/thiny If you want to change the id because the business meaning has changed, then you have conflicting goals.

Goal 1) Your thingy/object needs an immutable reference for the lifetime of the item.

Goal 2) Your business meaning wants to track some state change.

In this case it makes sense to seperate the fields containing the two distinctly different pieces of information with different purposes.


This is mostly fine. Infact, almost all my db tables have unique ids (serials) as their PKs.

The problem arises with some lookup-table. Something like Currencies, in example, which is made of a 3-char id (EUR, USD, AUD, ecc.) and some other infos. Or even Languages, identified by a 2-char id. This kind of ids may be seen as quasi-immutable, but sometimes (probably as a consequence of a previous user error), they may need to be changed. It is not really a change in business semantic of the persisted object, it is just a fix.

Most RDBMS do support the ability to propagate a change in the PK of an object to all its relatives, while the original instance (the row) remains the same.

In this, I see now that Hibernate is more close to the ejb layer than to the jdbc one. This, I believe, is not always good. Expecially when the EJB specs dictate for immutable ids more as a last restort to avoid troubles with instance reference, than as a mean to enforce good code development and data structuring.

Many good RDBMS solved this problem with OIDs, leaving the need for an immutable id somehow concealed with respect to the persisted data. This makes sense to me: I never saw an application directly handling OIDs, while they are very useful to a whole spectrum of tools and layers which may occasionally inspect or interface the database (think to db administration tools, or to event triggering).

On the contrary, EJB didn't approach the "immutability problem", leaving its solution to the developer. The fact that Hibernate follows the EJB trail in this enforces a pattern even when it would be less than an issue (ie.: when ejb technology isn't involved at all).


Quote:
If you REALLY REALLY want to "move" the primary key, then you have to:

1) Create the same instance at the new primary key id.
2) Update all references to the old value across your entire database schema.
3) Delete the old instance at the old id.

...


Well, of course I'm going to add some "native" ids to the "bad" tables...

Thanks again,

_________________
Giampaolo Tomassoni
Italy


Top
 Profile  
 
 Post subject:
PostPosted: Sun Jul 17, 2005 1:15 am 
Senior
Senior

Joined: Tue Jun 21, 2005 10:18 am
Posts: 135
Location: South Carolina, USA
Quote:
Thank you for your reply: it lets me understand why hibernate behaves this way. It is to comply with EJB specs.

Huh? Hibernate != EJB. It doesn't conform at all to EJB specs... it is an entirely different framework (unless you consider the relationship between hibernate and EJB3 :-) )


Quote:
The problem arises with some lookup-table. Something like Currencies, in example, which is made of a 3-char id (EUR, USD, AUD, ecc.) and some other infos. Or even Languages, identified by a 2-char id. This kind of ids may be seen as quasi-immutable, but sometimes (probably as a consequence of a previous user error), they may need to be changed. It is not really a change in business semantic of the persisted object, it is just a fix.

To me this is a very different problem. I would suggest that if these are truly "quasi-immutable" -- meaning you almost never change them -- that you simply perform the necessary updates using a generic database/SQL program and then, if you use the second level cache for these objects, simply restart it to avoid any cache-concurrency issues. Of course, this assumes that you have the CASCADE UPDATEs you mentioned. (The database I work with most (DB2/390) doesn't offer this :( ).


Quote:
I see now that Hibernate is more close to the ejb layer than to the jdbc one

If you are saying that hibernate is more similar to EJB CMP entity beans than to JDBC, then yes, I agree. Both are ORM solutions, whereas JDBC is a data access API for SQL databases. The two are not exactly mutually exclusive: both EJB CMP beans and Hibernate use JDBC for data access.


Quote:
On the contrary, EJB didn't approach the "immutability problem", leaving its solution to the developer. The fact that Hibernate follows the EJB trail in this enforces a pattern even when it would be less than an issue (ie.: when ejb technology isn't involved at all).

Aside from the OID solution (which is implemented differently/not at all in different RDBMSs), it is worth arguing that this is an issue, even when we don't use an ORM layer. Consider a concurrent system (i.e. web app) where two users are working with the same row in the database:

- We have a table containing key/value pairs, where the key is a mutable two-char code, and the value is a string description.

- User1 requests an update page for the row identified by "AB".

- User2 requests the same page for the same row.

- User2 changes the key of the row from "AB" to "AC" and submits his changes. The database is changed with:
Code:
UPDATE VALUES_TABLE SET KEY = "AC" WHERE KEY = "AB"
1 row is updated.

- User1 changes the description of the row from "A bird" to "A cat" (stupid example, but you get the idea). Remember, he still has a "reference to the "AB" row. An update is attempted with:
Code:
UPDATE VALUES_TABLE SET DESCRIPTION = "A cat" WHERE KEY = "AB"
0 rows are updated.

We are working without an ORM layer, but we still face a problem with mutable IDs. ORM simply forces you to face the problem during design.


Top
 Profile  
 
 Post subject:
PostPosted: Sun Jul 17, 2005 1:17 am 
Senior
Senior

Joined: Tue Jun 21, 2005 10:18 am
Posts: 135
Location: South Carolina, USA
eagle79 wrote:
simply restart it


Sorry, I meant restart your application. This is, of course, making the assumption we are talking about a "served" application (most likely a web application)


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 6 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.