Re: Persistence Strategies [Was: Open source WO - offer]
Lenny Marks <[email protected]> Tue, 5 Sep 2006 20:37:19 -0400
| Newsgroups | gmane.comp.web.webobjects.general |
|---|---|
| Message-ID | <[email protected]> |
On Sep 5, 2006, at 12:27 PM, Andrus Adamchik wrote: > On Sep 5, 2006, at 7:31 PM, Lenny Marks wrote: >> Just to expand, the benefit of POJO model objects is in the fact >> that they have no dependencies on the persistence framework(in >> this case Hibernate), which means any business logic can be easily >> tested with a Plain Old Unit Test in isolation without loading >> configuration files or connecting to a database, or any other >> complication. > > I think the above is an argument for POJO vs. EJB. Not POJO vs. > EO's or Cayenne DataObjects that are both actually POJO's from the > unit testing perspective. I.e. if you manually inflate your object > with test data values prior to testing the business logic, all ORM > frameworks should work the same. > Well, yes and no. I can't speak about Cayenne, but you can't do much with EOEnterprise objects without editing contexts and the model bundles loaded. I remember seeing a lot of' java.lang.IllegalStateException: Unabled to find an EOClassDescription..' exceptions if the EOModels weren't loaded. Just getting all the dependent frameworks and models loaded outside of a WOApplication is non-trivial. Hibernate imposes nothing on your model classes. You won't even see hibernate in an import statement. We used to have all our unit tests extending a base test class that took care of the dirty work, but in Hibernate POJO means POJO. Also, in EOF, most unit tests look something like this: <code> EOEditingContext ec = new EOEditingContext(); //has dependencies Employee emp = (Employee)EOUtilities.createAndInsertIntance(ec, "Employee"); Department department = (Department)EOUtilities.createAndInsertIntance (ec, "Department"); department.addObjectToBothSidesOfRelationshipWithKey(emp, "employees"); assertEquals(...something) </code> I would argue that POJO looks like this: <code> Employee emp = new Employee(); Department department = new Department(); department.addToEmployeesRelationship(emp); //granted I would have had to write this method in hibernate assertEquals(..something) </code> Prettiness only goes so far, but the dependencies of EOF are a bigger problem. I just ran an experiment running a single test method, EOF version vs POJO version. The EOF version takes about 1030 milliseconds and the POJO version takes about 300. Doing test first development, this adds up. > But not having a framework-mandated superclass can be good (or bad) > in different situations, that's for sure. A framework superclass > saves you time coding many things (and attach/detach thing IS > annoying), but can have unpredictable consequences during > serialization (e.g. when the objects have to cross the wire), and > makes it impossible for another framework to dictate a superclass :-) Yes, there is a good and a bad. Having model classes with no dependencies on the ORM solution makes them really lightweight and portable, but you also lose things like automatic validation before saving. Hibernate allows you to implement an interface of callbacks to do such stuff, but its not recommended because of the leakage of concerns. > >> Its also good for re-usability and maintainability not having your >> business entity classes and business logic tied to a particular >> ORM solution. > > True in general. Still if you code your business logic only relying > on public properties of the entities, the two approaches are > equivalent. Except that you can't re-use or test them without all of EOF and its dependencies. > >> The reason you have to make sure the Hibernate session is either >> closed or at least disconnected after each request is so the JDBC >> connection is released. In EOF, you don't need to worry about this >> because there is for the most part, a single open database >> connection shared by all editing contexts across the entire >> application or at least each EOF stack. > > You don't have to worry about it in Cayenne either, and it is fully > multithreaded with a connection pool (javax.sql.DataSource) behind it. > >> Speaking of caching. As I mentioned above, this was another place >> I found EOF to be flawed. Our experience wast that, EOF is great >> for read mostly applications or single instance applications that >> handle all database updates, or for applications without fresh >> data requirements. IMO, EOF applications get way too complicated, >> if this is not the case, for example if for whatever reason you >> have database updates happening outside of your app(legacy system) >> or because you have more than one instance of your app, or >> multiple apps manipulating the same data, or whatever... > > Stale data is a problem with any system that has a cache, period. > Not sure how Hibernate implements caching, but if you refetch > everything from scratch with EOF and/or Cayenne on every request, > you get fresh data, if you don't - you can end up with stale data. > As you mention below, its in the granularity of the caching. Stale data is a problem is any system with a cache, so that's why you wouldn't want to cache data that is frequently modified. Also in EOF, you can't refetch everything from scratch without the pretty severe side effect of tying up the EOF stack(path to database) blocking out all other requests. If you decide to give each request its own EOF stack, then each request has to open its own database connections. Also, EOF was definitely not intended to be used this way and so is still doing a lot of extra caching and notifications, which I would imagine have some impact on memory and performance. Of course you can start pooling EOObjectStoreCoordinators(I believe Wonder has support), but like I said, in EOF it just gets more complicated than it should be. I was actually the implementor of the JavaPoolingJDBCAdaptor framework posted on WOCode long ago, which was partially picked up in the latest Wonder release. I originally implemented that with great pain for a XML-RPC service that needed fresh data for every request so that all EOF stacks could share a pool of JDBC connections. > What EOF is missing is user friendly cache management facilities. > Expanding on your point - one size doesn't fit all, so making it > easier to implement alternative caching strategies is needed. > Cayenne is half-way there - we are doing some work on it in 3.0. > >> I'm not too familiar with Cayenne. We checked it out about a year >> ago, but thought it might be a little too much like EOF > > Not in the threading part ;-) Is Cayenne similar in architecture with something that looks like an EOF stack(Object store hierarchy)? If so, do developers have to manage locking/unlocking it like in EOF. Bottom line, can more than one request do database access without blocking others(by default)? > >> and at the time did not support POJO's which have been of >> substantial benefit. I'd be interested to here comments if Cayenne >> addresses some of these issues. > > DataObjects (and more so Persistent objects used in the remote > layer) are POJO's, except for the framework callbacks in the set/ > get methods. We just need to replace them with runtime class > enhancement (we still want lazy faulting and automatic reverse > relationship connection/disconnection, don't we?). Lazy faulting is definitely a good thing . Not sure what you mean exactly by reverse relationship connection/disconnection. If that means persistence by reachability, then also a good thing. One note about the runtime class enhancement. This is one of those complaints I have about Hibernate. It may just go with the territory, but the runtime class enhancement adds a substantial amount of startup time which hurts developer productivity. There seems to be some technical reason why Hibernate can't give an option to to build time class enhancement during development, which could be done only when a mapping has changed. Maybe you can avoid that when the time comes. > > Since we are targeting full JPA spec compliance, you'll see lots of > things familiar from Hibernate (and TopLink) world - again, attach/ > detach/getTransaction and other fun stuff. Ah. Thats sounds good. I didn't even go into transaction management, which is another place IMO, Hibernate wins over EOF. Doing declarative transaction management with Spring is really nice. -lenny