max wrote:
If I understand your C correctly you want several options:
0. Allow the user to specify a subset of columns that will be used as part of the where when doing an update.
That is right. That is what I meant by "fine-grained" in this context. The granularity is saying: which columns do I check to ensure I'm not violating concurrency.
max wrote:
but to support the "fine-grained control" you would also need:
1. "column"-lock mode that can be specified on each update - not just globally per entity/class - right ?
I see less of a need for this, but more to the point that is a question of making concurrency altogether optional on some rows. Since that is not a per-entity decision it is not helped by the logic of entity (o/r) mapping. Instead frameworks (or "services") like Hibernate offer these features in the same way that Hibernate supports arbitrary PKs -- e.g., the method for checking if an ID is set or not so that either an Insert or Update can be performed as appropriate. That is per-instance, not per-class logic. The same would be needed here. You could tell hibernate that the concurrency logic is handled by the class (or some controller class) and give it a method to invoke. That method would distinguish between whether that row needs concurrency or not. Anyway, it is not what I mean by "fine-grained" in this case.
max wrote:
Do you really use this generally for optimistic locking ? I have a hard time believing that this is a "very much used" optimistic locking scheme....
It is essential. At least the #3 version of it: check all columns. There is no other way to ensure that a Hibernate enabled app isn't trampling an existing system's updates. That is bad. It means I can not rely on Hibernate to do updates in those scenarios (a common one!).
max wrote:
I follow the advantages - but geez there are also alot of "whoops - forgot to include the right columns" and "whoops - needs this unindexed column for proper locking" risici. I see the version field as a much easier to understand/use, safer, faster and way more used ;)
The first part of that is an entirely spurious argument. By that logic (i.e., developers are dumb) no one has the right to program their computer let alone do so in Java. For the second part, see A & B with its problems. (Version counting is ok when you have control over all access methods to the DB. Otherwise it is a quick-fix. An often-used one, perhaps, but can be dangerous.)
max wrote:
...but hey, you are more than welcome to add a jira for it and let people vote for it ....or even submit a patch for it....it all get's more listened to ;)
Now we get into implementation details. For this to work, Hibernate needs to keep information about the original state of an object when it was fetched (aka "snapshots") and have that available at commit time. (My guess is this is already being done for one column: the timestamp or update count column). If Hibernate is already storing fetch timestamps or update counts anyway then it could store more info.
There are different places this can be done: in a session on read, in an object instance itself on first not-from-db write to a field, or somewhere else (e.g., a hashmap keyed by object class+PK). The problem with in the session is this probably won't work with disconnected objects. The problem with doing it in each class is that either (a) hibernate's no-base-class-required scheme gets violated (not recommended) or (b) each class has to do the work itself with a copy on write for its attributes -- possibly with a little help from a built-in helper class. It could implement an interface to indicate that it has the info to support column-level concurrency. (c) The problem with this (global) approach is that it is per JVM so if 2 different users modify a single object -- they see the same values in their browser but update of one is after the other -- the global snapshot will agree with the DB and the second update will succeed even though it is perhaps over-writing values set via the very same app by a different user...
So the first question is: where to keep the original values. I do not know the architecture of hibernate well enough to know off-hand.
As for granularity that's less needed. It would be easy to add via a per-property attribute once the original values were available. Anyway, for my needs it would be acceptable if the "check all columns" approach were implemented. While coarse-grained, it is at least friendly to other (existing) clients of the DB.
== Ezra Epstein