RE: Oh, yeah...

From: Gentry, Michael (michael_gentr..anniemae.com)
Date: Wed Sep 08 2004 - 12:52:30 EDT

  • Next message: Bryan Dyck: "Re: Cayenne + Tomcat (5)"

    OK, I finally had time to work on this and just got it working and
    thought I'd share in case it helps. I was missing a step, too. I'm
    trying to create a web-based utility application which can access
    different databases, all of which contain the same schema, and the
    different databases need to be accessed at the same time (they only
    share the schema, not the data). I also wanted it simpler to maintain
    (didn't want to copy/paste entity information all over the place).

    My model now has 4 DataDomains (one of which is "shared"), each with a
    DataNode pointing to a separate DB. 3 of the DataDomains do *not*
    contain a DataMap (no DB or Java entities), only a DataNode pointing to
    separate DBs. At run-time, I copy the shared DataMap into the
    DB-specific DataDomains. This way, I can create a DataContext,
    specifying the DataDomain I want to use.

    In brief:

    1 shared DataDomain which contains 1 shared DataMap with all the DB/Java
    information and 1 DataNode with the shared DataMap under it. I'm not
    even certain I need the DataNode here (haven't tried deleting it yet).

    3 DataDomains, each of which contains 1 DataNode with NO DataMap
    information (at the node or domain level). The DataMap information is
    obtained from the shared DataDomain/Map.

    Some Java code to map the shared information to the DB-specific domains:

      // This does the "hard" work of mapping the shared model to the domain
      private static void prepareDataDomain(String dataDomainName)
      {
        DataDomain dataDomain =
    Configuration.getSharedConfiguration().getDomain(dataDomainName);
        DataDomain sharedDataDomain =
    Configuration.getSharedConfiguration().getDomain("SharedModel");
        
        // Add the shared map to the data domain
        dataDomain.addMap(sharedDataDomain.getMap("SharedMap"));
        
        // Add the shared map to the data node
        Collection nodes = dataDomain.getDataNodes();
        
        if (nodes.size() != 1)
        {
          System.out.println("Expected only one DataNode for DataDomain '" +
    dataDomainName + "' -- this DataDomain is not usable.");
          return;
        }
        
        Iterator dataNodeIterator = nodes.iterator();
        
        // We are only getting one, though ...
        while (dataNodeIterator.hasNext())
        {
          DataNode node = (DataNode) dataNodeIterator.next();
          
          node.addDataMap(sharedDataDomain.getMap("MCodesSharedMap"));
        }
      }

      // Setup a domain -- only do this once!
      prepareDataDomain("DomainA");
      prepareDataDomain("DomainB");
      prepareDataDomain("DomainC");

      // Use a specific domain to get/update data
      DataContext dataContext = DataContext.createDataContext("DomainB");
      ...
      List objects = dataContext.performQuery(someQuery);

    The DataDomain you specify when you create the DataContext will now
    drive which database the objects are fetched from (and
    inserted/updated/deleted) when you perform your operations.

    Hope that can help someone ...

    /dev/mrg

    -----Original Message-----
    From: Gentry, Michael
    Sent: Monday, August 02, 2004 11:04 AM
    To: Todd O'Bryan; cayenne-use..bjectstyle.org
    Subject: RE: Oh, yeah...

    Funny you should ask that ... I had asked Andrus about that the other
    day. It's a little tricky, but here is the basic idea (note: I haven't
    had time to test this yet, so please let us know if it works):

    1. Create a "shared" DataDomain and DataMap in Cayenne Modeler. This
    will contain your schema definition. You won't need a DataNode here.

    2. Create a DataDomain for each DB you need to access (production and
    test, in your case). You will use these DataDomains later on to suck in
    the shared DataMap you created (step 1).

    3. Underneath each DB-specific DataDomain (step 2), create a DataNode
    with the JDBC connection for each environment's DB. You won't need a
    DataMap here.

    4. At run-time, you'll need to copy the shared DataMap into your
    DB-specific DataDomain. Check out
    Configuration.getSharedConfiguration.getDomain(dataDomainName). Use it
    to get your skeleton DB-specific DataDomain and the shared DataDomain.
    Then use
    skeletonDataDomain.addMap(sharedDataDomain.getMap("MySharedDataMap"))
    which should copy the shared schema into the skeleton one.

    That's as far as I've gotten so far. Other things interrupted my
    testing this out. I did have a few funky problems with the modeler, but
    you can work through them. You might also have to remove the shared
    DataMap (see removeMap("MySharedDataMap")) -- not certain, but you'd
    have two maps with entities with the same name otherwise. I hope not,
    because I was looking into making a utility application that could
    access our development/testing/acceptance/production DBs, all at the
    same time within the same web application. Basically, the schema is
    identical, but the connection dictionary differs.

    Please let us know how it works for you. If you don't need multiple
    connections, it might be much easier to just change the connection
    dictionary at deployment time.

    Thanks,

    /dev/mrg

    -----Original Message-----
    From: Todd O'Bryan [mailto:toddobrya..ac.com]
    Sent: Monday, August 02, 2004 8:59 AM
    To: cayenne-use..bjectstyle.org
    Subject: Oh, yeah...

    The other part of that question is, is there a way to have the same
    Cayenne configuration file be set up to connect to two different
    databases depending on a parameter, i.e., the production database and
    the test database?

    Thanks,
    Todd



    This archive was generated by hypermail 2.0.0 : Wed Sep 08 2004 - 12:52:35 EDT