No pun intended, but ot would be *nice* if you helped us testing one of the milestone builds, as that's the main reason why we are providing such builds. Ideally, the majority of the things should be tested before 1.1 final, and not after. I do acknowledge, though, that the community seems not to be sharing my view here .. ;-). But I'd like everybody to understand that his creates quite an additional load on us, the committres, that we'd like to avoid (if possible).
Werner > -----Original Message----- > From: James Abley [mailto:[EMAIL PROTECTED] > Sent: Donnerstag, 11. Jänner 2007 14:07 > To: [email protected] > Subject: Re: [castor-user] [JDO] Castor Locking on Object Graphs > > Hi Werner, > > I probably will do when I can upgrade, but I'm still on 0.9.6 > and unable to upgrade. The things that stopped me upgrading > [1] have been fixed, so I should hopefully be on 1.1 when it > gets released and I get round to testing it. > > Cheers, > > James > > [1] http://jira.codehaus.org/browse/CASTOR-1688 > > Werner Guttmann wrote: > > 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 > > > > > --------------------------------------------------------------------- > 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

