Re: How to program against the ODMG personality correctly?
Sean Dockery wrote: Hello, Philippe. Thanks for the analysis and tip about the performance of ODMG in relation to caching objects. That is helpful. I have a question for you about your little snippet... PersistenceBroker broker = ((TransactionImpl) tx).getBroker(); A aDummyObject = new A(); aDummyObject.setId(id); Query qry = new QueryByIdentity(aDummyObject); A result = (A) broker.getObjectByQuery(qry); On the OJB web site, it shows the following usage. PersistenceBroker broker = ((HasBroker) tx).getBroker(); The use of "HasBroker" seems cleaner than "TransactionImpl" to me. I know that since 0.9.8 that classes have disappeared. :-( (I'm working on an application that uses a closed-source third party library based on OJB 0.9.8; I know that classes have disappeared because I couldn't run the application with OJB 1.0.) I agree with you. If it's written in the docs, there are more chances that the HasBroker interface will be upward compatible, compared to the TransactionImpl class. You could also do this instead... Identity identity = new Identity(aDummyObject); A result = (A) broker.getObjectByIdentity(identity); Is there any difference in behaviour betwen "getObjectByQuery" and "getObjectByIdentity" when it comes to caching? Or is it just a style (using query vs. identity) preference? You mean: Identity identity = new Identity(aDummyObject,broker) ? I think you are right. Looking back at the PersistenceBrokerImpl source code, it looks like getObjectByIdentity() is more efficient than getObjectByQuery(). I tried to avoid the PB API and stick to the ODMG, until I ran into performance problems and struggled to make a better use of the cache, that's why I may not use the PB at best. One more thought: use of the default cache is great, as long as there is no external process making changes in the database, outside of this instance of OJB, which is the case in my app. But if this is not the case (a web app deployed in a cluster without a distributed cache,...), the default behavior of the ODMG queries looks good to me: the DB is checked to make sure there has not been a modification in the data. Thanks again, Philippe. I look forward to your reply. You are welcome, I like such profitable exchanges of views. - To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
Re: How to program against the ODMG personality correctly?
Hello, Philippe. Thanks for the analysis and tip about the performance of ODMG in relation to caching objects. That is helpful. I have a question for you about your little snippet... > PersistenceBroker broker = ((TransactionImpl) tx).getBroker(); > A aDummyObject = new A(); > aDummyObject.setId(id); > Query qry = new QueryByIdentity(aDummyObject); > A result = (A) broker.getObjectByQuery(qry); On the OJB web site, it shows the following usage. PersistenceBroker broker = ((HasBroker) tx).getBroker(); The use of "HasBroker" seems cleaner than "TransactionImpl" to me. I know that since 0.9.8 that classes have disappeared. :-( (I'm working on an application that uses a closed-source third party library based on OJB 0.9.8; I know that classes have disappeared because I couldn't run the application with OJB 1.0.) You could also do this instead... Identity identity = new Identity(aDummyObject); A result = (A) broker.getObjectByIdentity(identity); Is there any difference in behaviour betwen "getObjectByQuery" and "getObjectByIdentity" when it comes to caching? Or is it just a style (using query vs. identity) preference? Thanks again, Philippe. I look forward to your reply. "Philippe Hacquin" <[EMAIL PROTECTED]> wrote in message news:[EMAIL PROTECTED] > Hi Sean, > > I'm not an OJB-ODMG expert, but maybe I can help > > Sean Dockery wrote: > > [...] > >>1) The exception handling code is omitted from the examples for the sake > > of brevity. Is the manner in which I'm handling exceptions correct? > > Take care of the following: > > Transaction tx = implementation.newTransaction(); > tx.begin(); > try > { > > tx.commit(); > } > catch (Throwable t) > { > tx.abort(); > throw new DaoException(t); > } > You may catch a TransactionAbortedException, which in this case will > leave tx null, thus you will end with a NPE if you execute tx.abort() > > > >> > >>2) I've written my retrieval routine to use a persistence broker query. > >>Using persistence broker queries in this manner is apparently faster. In > > a reply in another thread, I read... > >> > >>"Philippe Hacquin" <[EMAIL PROTECTED]> wrote in message > >>news:<[EMAIL PROTECTED]>... > >> > >>>... and they are much more efficient, too, because they use the cache. > >> > >>This confuses me somewhat. Does this mean that the ODMG personality of > > OJB doesn't use caching? Or do OQL queries bypass caching? > > I've recently made some performance tests, with p6spy and network traces > to monitor the queries sent to the database. I am using ODMG in OJB 1.0 > RC4, too. > Say you have a class A that has some properties, with at least the "id" > property which is mapped to the primary key of your table (hence, you > don't use anonymous keys). > You want to get a reference to a persistent object using the id. So you > write an OQL query like "select anInstance from " + A.class.getname() + > "where id = \"" + id + "\"" > Well, you have to know this ODMG query will lead to a straight SQL query > to the database, even if the object is already in the cache. But the > cache will anyway be looked up after the SQL query, to check if the > materialization process can be avoided. This process consumes some time, > you can check that during some tests. So an ODMG query uses the cache, > but does not use at 100%. > To use the cache in an effectively manner, you have to use a PB query > against the object Identity (well, this is what I deducted, if there is > a more efficient way to do it with the default cache, I'd like to hear > about it). > This is the way I code it: > > PersistenceBroker broker = ((TransactionImpl) tx).getBroker(); > A aDummyObject = new A(); > aDummyObject.setId(id); > Query qry = new QueryByIdentity(aDummyObject); > A result = (A) broker.getObjectByQuery(qry); > > This way the cache is looked up _before_ querying the DB. > This was not obvious when I began using OJB, but should have if I had > carefully read the "Object cache" documentation: the lookup() method > takes an Identity instance as search key in the cache. > Well, I supposed this was handled transparently in the ODMG > implementation layer... > > HTH - To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
Re: How to program against the ODMG personality correctly?
Hi Sean, I'm not an OJB-ODMG expert, but maybe I can help Sean Dockery wrote: [...] 1) The exception handling code is omitted from the examples for the sake of brevity. Is the manner in which I'm handling exceptions correct? Take care of the following: Transaction tx = implementation.newTransaction(); tx.begin(); try { tx.commit(); } catch (Throwable t) { tx.abort(); throw new DaoException(t); } You may catch a TransactionAbortedException, which in this case will leave tx null, thus you will end with a NPE if you execute tx.abort() 2) I've written my retrieval routine to use a persistence broker query. Using persistence broker queries in this manner is apparently faster. In a reply in another thread, I read... "Philippe Hacquin" <[EMAIL PROTECTED]> wrote in message news:<[EMAIL PROTECTED]>... ... and they are much more efficient, too, because they use the cache. This confuses me somewhat. Does this mean that the ODMG personality of OJB doesn't use caching? Or do OQL queries bypass caching? I've recently made some performance tests, with p6spy and network traces to monitor the queries sent to the database. I am using ODMG in OJB 1.0 RC4, too. Say you have a class A that has some properties, with at least the "id" property which is mapped to the primary key of your table (hence, you don't use anonymous keys). You want to get a reference to a persistent object using the id. So you write an OQL query like "select anInstance from " + A.class.getname() + "where id = \"" + id + "\"" Well, you have to know this ODMG query will lead to a straight SQL query to the database, even if the object is already in the cache. But the cache will anyway be looked up after the SQL query, to check if the materialization process can be avoided. This process consumes some time, you can check that during some tests. So an ODMG query uses the cache, but does not use at 100%. To use the cache in an effectively manner, you have to use a PB query against the object Identity (well, this is what I deducted, if there is a more efficient way to do it with the default cache, I'd like to hear about it). This is the way I code it: PersistenceBroker broker = ((TransactionImpl) tx).getBroker(); A aDummyObject = new A(); aDummyObject.setId(id); Query qry = new QueryByIdentity(aDummyObject); A result = (A) broker.getObjectByQuery(qry); This way the cache is looked up _before_ querying the DB. This was not obvious when I began using OJB, but should have if I had carefully read the "Object cache" documentation: the lookup() method takes an Identity instance as search key in the cache. Well, I supposed this was handled transparently in the ODMG implementation layer... HTH - To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
Re: How to program against the ODMG personality correctly?
I posted this right around new years, but I have not seen any responses since then and some of these questions are still eating at me. Can anyone provide any answers to some of the questions that I've asked? Thanks in advance. "Sean Dockery" <[EMAIL PROTECTED]> wrote in message news:[EMAIL PROTECTED] > Hello there. > > I'm fairly new to OJB. I've read several of the tutorials and I'm working > on creating an application from scratch. > > Below are three classes that I wrote. One is my DAO class, the second class > is an inversion-of-control interface that I'm using to populate the object > after locking it in the DAO class, and the last class is a Struts action > which using the DAO class and provides an implementation of the > UserConfigurator interface. > > I was wondering if anyone could provide some feedback and opinions about the > code. I'm mainly curious about the following: > > 1) The exception handling code is omitted from the examples for the sake of > brevity. Is the manner in which I'm handling exceptions correct? > > 2) I've written my retrieval routine to use a persistence broker query. > Using persistence broker queries in this manner is apparently faster. In a > reply in another thread, I read... > > "Philippe Hacquin" <[EMAIL PROTECTED]> wrote in message > news:<[EMAIL PROTECTED]>... > > ... and they are much more efficient, too, because they use the cache. > > This confuses me somewhat. Does this mean that the ODMG personality of OJB > doesn't use caching? Or do OQL queries bypass caching? > > 3) I've chose to perform object deletion using the persistence broker > instead of database.deletePersistent. What is the consequence of using one > over the other? > > 4) The PB transaction mechanism uses database locks. The ODMG personality > uses object locks. Yet, the ODMG personality is less performant than the PB > personality (according to the performance page on the web site.) Last time > I checked, memory operations were less expensive than database I/O--so I > would have expected ODMG to out-perform PB. Can anyone explain this > apparent contradiction? > > 5) I've seen an application that uses OJB that performs updates directly > against the database using JDBC. I suspect that the implication is that > cached objects can become out of sync with data in the database. Does OJB > have a means by which to detect that a row has been changed by another user? > > 6) The auto-retrieve attribute must (apparently) be set to true for ODMG. > This seems a little evil in that I will always be retrieving a graph of > objects instead of the single object in which I'm interested. The > application mentioned in question 5 has severe performance problems related > to database access; I suspect that the root of the performance problems are > being caused by having auto-retrieve set to true for several key entities in > the application. What happens to the behaviour of the ODMG implementation > if auto-retrieve is set to false? (It suggests that this is a no-no on the > web site, but doesn't elaborate on what problems will arise.) Should I be > switching to the PB personality of OJB to avoid problems? > > 7) Why would I choose to use the ODMG personality over the PB personality? > I've seen some (rather unhelpful) replies saying "it depends on your needs" > and I'm looking for something a little more insightful. What does using the > ODMG personality get me? (I'm not sure what "real Object Transactions" are > supposed to be, but that is one of the reasons cited on the web site.) > > Thanks very much for your precious time. It is greatly appreciated. > > UserDao.java: > package catalyst.dao; > import org.apache.ojb.broker.PersistenceBroker; > import org.apache.ojb.broker.query.Criteria; > import org.apache.ojb.broker.query.Query; > import org.apache.ojb.broker.query.QueryFactory; > import org.apache.ojb.odmg.HasBroker; > import org.apache.ojb.odmg.OJB; > import org.odmg.Implementation; > import org.odmg.Transaction; > import catalyst.domain.User; > public class UserDao { > private static UserDao instance = new UserDao(); > private UserDao() { > } > public static UserDao getInstance() { > return instance; > } > private User findUser(Integer userId) throws DaoException { > Implementation odmg = OJB.getInstance(); > Transaction tx = odmg.newTransaction(); > tx.begin(); > try { > PersistenceBroker broker = ((HasBroker) tx).getBroker(); > Criteria criteria = new Criteria(); > criteria.addEqualTo("userId", userId); > Query query = QueryFactory.newQuery(User.class, criteria); > User user = (User) broker.getObjectByQuery(query); > tx.commit(); > return user; > } > catch (Throwable t) { > tx.abort(); > throw new DaoException(t); > } > } > private void storeUser(User user, UserConfigurator configurator) throws > DaoException { > Implementation implementation = OJB.getInstance(); > Transaction tx = implementation.newTransaction(); > tx.begin(); > try { > tx.lock(user, Transaction.WRITE); > configu
How to program against the ODMG personality correctly?
Hello there. I'm fairly new to OJB. I've read several of the tutorials and I'm working on creating an application from scratch. Below are three classes that I wrote. One is my DAO class, the second class is an inversion-of-control interface that I'm using to populate the object after locking it in the DAO class, and the last class is a Struts action which using the DAO class and provides an implementation of the UserConfigurator interface. I was wondering if anyone could provide some feedback and opinions about the code. I'm mainly curious about the following: 1) The exception handling code is omitted from the examples for the sake of brevity. Is the manner in which I'm handling exceptions correct? 2) I've written my retrieval routine to use a persistence broker query. Using persistence broker queries in this manner is apparently faster. In a reply in another thread, I read... "Philippe Hacquin" <[EMAIL PROTECTED]> wrote in message news:<[EMAIL PROTECTED]>... > ... and they are much more efficient, too, because they use the cache. This confuses me somewhat. Does this mean that the ODMG personality of OJB doesn't use caching? Or do OQL queries bypass caching? 3) I've chose to perform object deletion using the persistence broker instead of database.deletePersistent. What is the consequence of using one over the other? 4) The PB transaction mechanism uses database locks. The ODMG personality uses object locks. Yet, the ODMG personality is less performant than the PB personality (according to the performance page on the web site.) Last time I checked, memory operations were less expensive than database I/O--so I would have expected ODMG to out-perform PB. Can anyone explain this apparent contradiction? 5) I've seen an application that uses OJB that performs updates directly against the database using JDBC. I suspect that the implication is that cached objects can become out of sync with data in the database. Does OJB have a means by which to detect that a row has been changed by another user? 6) The auto-retrieve attribute must (apparently) be set to true for ODMG. This seems a little evil in that I will always be retrieving a graph of objects instead of the single object in which I'm interested. The application mentioned in question 5 has severe performance problems related to database access; I suspect that the root of the performance problems are being caused by having auto-retrieve set to true for several key entities in the application. What happens to the behaviour of the ODMG implementation if auto-retrieve is set to false? (It suggests that this is a no-no on the web site, but doesn't elaborate on what problems will arise.) Should I be switching to the PB personality of OJB to avoid problems? 7) Why would I choose to use the ODMG personality over the PB personality? I've seen some (rather unhelpful) replies saying "it depends on your needs" and I'm looking for something a little more insightful. What does using the ODMG personality get me? (I'm not sure what "real Object Transactions" are supposed to be, but that is one of the reasons cited on the web site.) Thanks very much for your precious time. It is greatly appreciated. UserDao.java: package catalyst.dao; import org.apache.ojb.broker.PersistenceBroker; import org.apache.ojb.broker.query.Criteria; import org.apache.ojb.broker.query.Query; import org.apache.ojb.broker.query.QueryFactory; import org.apache.ojb.odmg.HasBroker; import org.apache.ojb.odmg.OJB; import org.odmg.Implementation; import org.odmg.Transaction; import catalyst.domain.User; public class UserDao { private static UserDao instance = new UserDao(); private UserDao() { } public static UserDao getInstance() { return instance; } private User findUser(Integer userId) throws DaoException { Implementation odmg = OJB.getInstance(); Transaction tx = odmg.newTransaction(); tx.begin(); try { PersistenceBroker broker = ((HasBroker) tx).getBroker(); Criteria criteria = new Criteria(); criteria.addEqualTo("userId", userId); Query query = QueryFactory.newQuery(User.class, criteria); User user = (User) broker.getObjectByQuery(query); tx.commit(); return user; } catch (Throwable t) { tx.abort(); throw new DaoException(t); } } private void storeUser(User user, UserConfigurator configurator) throws DaoException { Implementation implementation = OJB.getInstance(); Transaction tx = implementation.newTransaction(); tx.begin(); try { tx.lock(user, Transaction.WRITE); configurator.configure(user); tx.commit(); } catch (Throwable t) { tx.abort(); throw new DaoException(t); } } public void createUser(UserConfigurator configurator) throws DaoException { storeUser(new User(), configurator); } public void updateUser(Integer userId, UserConfigurator configurator) throws DaoException { storeUser(findUser(userId), configurator); } public void deleteUser(Integer userId) throws DaoException { Implementation odmg = OJB.getInstance(); Transaction tx = odmg.newTransaction(); tx.begin