Let me also point that what I am suggesting is exactly the same as what Michael did. The difference lies in the presence of an IoC container and all the data access methods moved out of DataObjects to the "DAO services".

In some applications picking one or the other style makes no difference. Where it does make a difference is when the same set of DAO interfaces has to work differently depending on some environment parameters. So you have more than one implementation of a given DAO all using the same shared Cayenne mapping. Simple example - a CMS application running in two modes: "production" and "preview", and there is a PageDAO that provides access to persistent Page objects. Production-mode DAO may avoid returning pages whose state is "not published", while preview mode DAO will return them to the caller.

Andrus


On Apr 21, 2009, at 4:43 PM, Andrus Adamchik wrote:

Yeah, it depends greatly on the general app architecture and usage patterns... IIRC the petstore example was taken from Spring and rewritten with Cayenne, so it may have some of the Spring-induced artifacts (don't remember all the details).

The pattern I am personally following lately in the systems that have an IoC container (say Spring or Tapestry), is to define one generic Cayenne "service" that gives access to an ObjectContext depending on your needs, and a bunch of "DAO services" that encapsulate specific queries and other data operations, including cache strategies. This way the frontend code doesn't have to deal with cache rules and other low level details. This requires some thought on the design, but at the end scales best in terms of complexity.

Here is some examples:

interface CayenneService {
// depending on implementation this can return application or session-level shared context.
  // often this is a read-only context...
  ObjectContext getSharedContext();

  // creates a new context
  ObjectContext createNewContext();
}

interface AccountDAO {

  List<Account> getActiveAccounts();

  List<Account> getNewAccounts();

  List<Account> searchAccounts(Stirng searchCriteria);
}


class AccountDAOImpl implements AccountDAO {

  // injected
  CayenneService cayenneService;

  List<Account> getActiveAccounts() {
      SelectQuery query = new SelectQuery(Account.class);
      query.andQualifier(...);
      query.andQualifier(...);

      query.setCacheStrategy(...);
      query.setCacheGroups(...);

      return cayenneSerice. getSharedContext().performQuery(query);
  }
}

Andrus

On Apr 21, 2009, at 4:26 PM, Michael Gentry wrote:
I'm not familiar with the Pet Store example, so I'm not sure what was
meant by it not being a best practices example.  Also, people have
many different ideas of what they think a best practice is, so it can
vary greatly.

My typical usage is to put my custom business logic in the
Cayenne-generated subclass and to also put my "fetch" type methods in
there, too (when not creating them in Cayenne Modeler).  The more
interesting questions (to me) are what are the usage patterns, etc.
That helps determine how to use the DataContext (or ObjectContext),
how to do data refreshing, etc.  One application I did had a single
read-mostly DC that I synchronized access to for all the users (the
queries took a prohibitive amount of time for interactive usage, so I
cached things in a single DC).  Others I used one (or more) DCs per
user's session.  Again, it really depends upon what your requirements
are for data access.

Feel free to ask more questions.  Hope that helped just a little.

mrg


On Mon, Apr 20, 2009 at 3:30 PM, Ylan Segal <[email protected]> wrote:
Hi Everyone,

I am new to Cayenne. I was looking at the examples in the wiki, especially
at the pet store:

http://cwiki.apache.org/CAY/cayenne-petstore.html

So far, I like what I see. The above page does mention that the pet store example "... definitely needs a rewrite and DB redesign before we can call
it Cayenne Best Practices Demo."

Why isn't it a best practice? Because of the DB design or because of how Cayenne classes are used? The overall app design (one domain package, one DAO package, one presentation package) seems reasonable to me. I would be designing a DB schema from scratch for a web application (probably with struts), and I am thinking of following the example pattern, assuming that pattern is not what needs rewriting! Can anyone suggest best practices for this type of situation? I am looking for more of a "what packages should we have" discussion rather than a "this is how you save an object to the
database" discussion.

I hope this makes sense.

--
Ylan Segal
[email protected]






Reply via email to