James, Why don't you actually use Database.getJdbcConnection() instead ? Iow, your code could look similar to
Database db = jdo.getDatabase(9; db.begin(); Connection connection = db.getJdbcConnection(); ... db.commit(); db.close(); Werner PS Apart from this, you could try to start using the Spring ORM implemention for Castor JDO, and then - when implementing individual methods of your DAOs - either use the CastorTemplate or the JDBCTemplate, whatever your preferences are. > -----Original Message----- > From: James Abley [mailto:[EMAIL PROTECTED] > Sent: Donnerstag, 11. Jänner 2007 11:37 > To: [email protected] > Subject: Re: [castor-user] [JDO] Castor Locking on Object Graphs > > Cheers Ralf, > > I'd guessed as much and have set the cache to none for that object. > Preliminary indications from running my tests show that the > application still works correctly using this hybrid approach > of Castor and JDBC. > This application should be the only thing writing to that > database, so otherwise the cache should work correctly, but I > might need to judiciously disable it for certain domain > objects. Shouldn't be a problem. > > I do have one question about it though. Obviously, I'd like > to utilise the same mechanism that Castor uses for retrieving > a JDBC Connection. > Initial browsing of the code makes me think that I can do it > fairly easily using this: > > /** > * Return a Connection, using the same mechanisms that > Castor uses, so > * hopefully doing the same ConnectionPool / JNDI lookup > whatever, that > * Castor is configured to use. > * > * @return a Connection - not null. > * @throws SQLException if there was a problem. > */ > private Connection getConnection() throws SQLException { > > // We know the name of the Database entry in the configuration is > // "default" > DatabaseRegistry databaseRegistry = DatabaseRegistry > .getDatabaseRegistry("default"); > return databaseRegistry.createConnection(); > } > > It seems to work, but it would be nice to have it confirmed > by someone more familiar with the code! > > Cheers, > > James > > Ralf Joachim wrote: > > Hi James, > > > > as far as I remember, CALL SQL does only work for select statements > > but not for update or insert. You have to use JDBC for this > kind of things. > > > > Having said that you have to take care on cached objects > that you have > > updated through JDBC. Castor does not know about the > database changes > > and will hold dirthy objects in its cache. This will lead to > > ObjectModifiedExceptions thrown when updating these objects through > > Castor. Another problem is that you do not instantly see > your changes > > done by JDB statements. Therefore you need to set cache > type to none > > or remove the updated object from cache. While I have used > the first > > myself I have no experience about the second solution. > > > > Regards > > Ralf > > > > > > James Abley schrieb: > >> Actually, it doesn't look like I can drop into raw SQL in this way. > >> > >> CALL SQL UPDATE myObject SET field = $1 WHERE ID = $2 > >> > >> That doesn't get parsed properly by OQLQueryImpl.createCall - it > >> looks for the WHERE clause and examines the statement for > $x tokens > >> after the string value WHERE, rather than checking the whole > >> statement. Later, > >> OQLQueryImpl.bind(Object) throws a NullPointerException > when it tries > >> to bind the first parameter, and can't find a ParamInfo > object in the > >> _paramInfo field keyed on Integer(1). > >> > >> So it looks like I will have to drop into JDBC to use this sort of > >> update approach. > >> > >> Should I raise a JIRA ticket about the OQL parsing? > >> > >> Cheers, > >> > >> James > >> > >> James Abley wrote: > >>> To provide more context, I'm seeing locking and > >>> LockNotGrantedException problems with a part of the > application that > >>> tries to update a single field in a root object, and > >>> LockNotGrantedExceptions happen over the root object, or > something > >>> in the related object graph. I'm leaning towards the idea of > >>> swapping out the current implementation for a simple raw > SQL 'UPDATE > >>> MyObject SET field = ? WHERE ID = ' approach to see if > that removes > >>> the problem and was wondering if anyone else has seen > similar issues > >>> or resorted to that type of thing? > >>> > >>> Cheers, > >>> > >>> James > >>> > >>> James Abley wrote: > >>>> Cheers Ralf and Werner, > >>>> > >>>> That tallies with my understanding. > >>>> > >>>> Does anyone have real-world examples they can share about > >>>> complexity of objects graphs that they have in their > domain? One of > >>>> the applications I deal with locks a lot of objects (maybe ten > >>>> objects) when a root object is loaded. > >>>> > >>>> Some of this (I believe) is mitigated since some of the domain > >>>> objects can be marked in the mapping file as read-only, and so I > >>>> would hope that Castor never gets any lock on that; e.g. > if one of > >>>> the objects references a Country object that is marked > as read-only > >>>> in the mapping file, any attempt to load something referencing a > >>>> Country object will always return that Country object as > read-only > >>>> and thus no transaction should experience race-conditions on > >>>> attempting to gain a lock on a Country object, no matter what > >>>> AccessMode is being used by the client transaction. > >>>> > >>>> But my main concern is whether having such a complex > object graph > >>>> is damaging to concurrency, and whether I should look at > >>>> de-normalisation to flatten it a bit. > >>>> > >>>> Cheers, > >>>> > >>>> James > >>>> > >>>> Werner Guttmann wrote: > >>>>> In addition to what Ralf has said, please note that loading > >>>>> objects as read-only mode (in one way or the other) > will help you > >>>>> improving performance as Castor will perform less checks at the > >>>>> end of the transaction. > >>>>> > >>>>> In other words, make sure that you know your domain model, > >>>>> especially when it comes down to categorizations such as > >>>>> 'stability', 'cacheability', etc. > >>>>> > >>>>> Regards > >>>>> Werner > >>>>> > >>>>> Ralf Joachim wrote: > >>>>>> Hi James, > >>>>>> > >>>>>> Castor locks the whole object graph from the time when it gets > >>>>>> loaded until the end of the transaction which is > _db.commit(). If > >>>>>> Castor would not lock the whole object graph that > could lead to > >>>>>> inconsistenties. > >>>>>> With > >>>>>> the default access mode 'Shared' these locks are handled by > >>>>>> Castor internally. > >>>>>> > >>>>>> As the transaction at your first example is open during 'some > >>>>>> long operation' the whole graph gets locked until the > end of this > >>>>>> transaction. > >>>>>> > >>>>>> At the second example you have 2 short transaction. > The first one > >>>>>> loads the object and thereafter releases any locks at first > >>>>>> _db.commit(). > >>>>>> According to this no object is locked during the 'some long > >>>>>> operation'. > >>>>>> After that operation you start the second transaction > which again > >>>>>> loads and locks the object including all related ones. > Then you > >>>>>> do some changes to the objects and commit them. At this commit > >>>>>> the changes are written to database and the locks get released > >>>>>> again. > >>>>>> > >>>>>> As the objects are not locked during 'some lock > operation' at the > >>>>>> second example, you need to be aware that your object may have > >>>>>> changed in the meantime. > >>>>>> > >>>>>> Hope this helps > >>>>>> Ralf > >>>>>> > >>>>>> > >>>>>> James Abley schrieb: > >>>>>>> Hi, > >>>>>>> > >>>>>>> I'm trying to understand Castor's locking mechanism > for object > >>>>>>> graphs. > >>>>>>> > >>>>>>> Say I have the following classes: > >>>>>>> > >>>>>>> class Book { > >>>>>>> > >>>>>>> int id; > >>>>>>> > >>>>>>> String author; > >>>>>>> > >>>>>>> ... > >>>>>>> } > >>>>>>> > >>>>>>> class Customer { > >>>>>>> > >>>>>>> int id; > >>>>>>> > >>>>>>> // Assume this will be a collection of Books that > >>>>>>> // has been browsed by each customer. > >>>>>>> Collection booksBrowsed; > >>>>>>> > >>>>>>> // Assume that this is the transaction history of > >>>>>>> // each customer, so a collection of Transaction > >>>>>>> // objects > >>>>>>> Collection transactions; > >>>>>>> > >>>>>>> Date lastLoginTime; > >>>>>>> > >>>>>>> ... > >>>>>>> } > >>>>>>> > >>>>>>> class Transaction { > >>>>>>> > >>>>>>> int id; > >>>>>>> > >>>>>>> Date purchaseTime; > >>>>>>> > >>>>>>> Book item; > >>>>>>> > >>>>>>> ... > >>>>>>> } > >>>>>>> > >>>>>>> If I have client code that does something like the following: > >>>>>>> > >>>>>>> > >>>>>>> Database db = getDatabase(); > >>>>>>> db.begin(); > >>>>>>> db.load(Customer.class, 3, Database.Shared); > >>>>>>> > >>>>>>> // do some long operation here > >>>>>>> > >>>>>>> customer.setLastLoginTime(Calendar.getInstance().getTime()); > >>>>>>> db.commit(); > >>>>>>> db.close(); > >>>>>>> > >>>>>>> > >>>>>>> Is there a lock held on all of the objects in the > collections in > >>>>>>> the Customer object? Or is a lock only obtained on > the Customer > >>>>>>> object when the transaction is ending and Castor can examine > >>>>>>> each object, see if it's dirty and thus needs to get > a lock to > >>>>>>> update the object? > >>>>>>> > >>>>>>> Second related part. I'm very familiar with > >>>>>>> http://www.castor.org/jdo-best-practice.html, but I > was curious > >>>>>>> about another aspect. Assume that I re-write the > client to try > >>>>>>> to minimize the > >>>>>>> transaction: > >>>>>>> > >>>>>>> > >>>>>>> Database db = getDatabase(); > >>>>>>> db.begin(); > >>>>>>> db.load(Customer.class, 3, Database.ReadOnly); db.commit(); > >>>>>>> db.close(); > >>>>>>> > >>>>>>> // do some long operation here > >>>>>>> db.begin(); > >>>>>>> db.load(Customer.class, 3, Database.Shared); > >>>>>>> customer.setLastLoginTime(Calendar.getInstance().getTime()); > >>>>>>> db.commit(); > >>>>>>> db.close(); > >>>>>>> > >>>>>>> > >>>>>>> Again, what gets locked? Is it the entire object > graph, or just > >>>>>>> the dirty objects? > >>>>>>> > >>>>>>> Presumably the latter code sample is the recommended > way to go, > >>>>>>> irrespective of how the object graph gets locked? > >>>>>>> > >>>>>>> Cheers, > >>>>>>> > >>>>>>> James > >>>>>>> > >>>>>>> > ---------------------------------------------------------------- > >>>>>>> ----- To unsubscribe from this list please visit: > >>>>>>> > >>>>>>> http://xircles.codehaus.org/manage_email > >>>>> > >>>>> > ------------------------------------------------------------------ > >>>>> --- To unsubscribe from this list please visit: > >>>>> > >>>>> http://xircles.codehaus.org/manage_email > >>>>> > >>>> > >>>> > ------------------------------------------------------------------- > >>>> -- To unsubscribe from this list please visit: > >>>> > >>>> http://xircles.codehaus.org/manage_email > >>>> > >>> > >>> > -------------------------------------------------------------------- > >>> - To unsubscribe from this list please visit: > >>> > >>> http://xircles.codehaus.org/manage_email > >>> > >> > >> > --------------------------------------------------------------------- > >> To unsubscribe from this list please visit: > >> > >> http://xircles.codehaus.org/manage_email > > > > > --------------------------------------------------------------------- > To unsubscribe from this list please visit: > > http://xircles.codehaus.org/manage_email > --------------------------------------------------------------------- To unsubscribe from this list please visit: http://xircles.codehaus.org/manage_email

