Re: Oh, yeah...

From: Bryan Lewis (brya..aine.rr.com)
Date: Wed Sep 08 2004 - 19:42:33 EDT

  • Next message: Todd O'Bryan: "Relationship across DataDomains (again)"

    Looks good. I've been using another method that achieves the same
    result, or maybe a more limited case of the same result, with a bit less
    code.

    I have three domain files. The one named cayenne.xml is the one for the
    development domain, the one I load in the modeler for all my datamap
    editing. The other two files have names like test.cayenne.xml and
    prod.cayenne.xml; they differ only in the DataNode.

    Cayenne.xml contains:

    <domain name="model">
       <map name="DataMap" location="DataMap.map.xml"/>
         <node name="DataNode"
               datasource="DataNode.driver.xml" .../>
           <map-ref name="DataMap"/>
         </node>
    </domain>

    Test.cayenne.xml is the same except for one line:

               datasource="TestDataNode.driver.xml" .../>

    In effect they're sharing a single DataMap as yours do.
    My startup code picks the right name to load:

         private static synchronized Configuration
             getConfiguration(String prefix)
         {
             Configuration config;

             // The prefix is, for example, "test.".
             String configName = prefix + "cayenne.xml";
             config = new DefaultConfiguration(configName);
             Configuration.initializeSharedConfiguration(config);

             return config;
         }

    Gentry, Michael wrote:
    > 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 - 19:42:41 EDT