You are viewing a plain text version of this content. The canonical link for it is here.
Posted to user@cayenne.apache.org by Lawrence Gerstley <la...@gmail.com> on 2009/01/06 02:57:25 UTC

Changing database schemas at runtime

Hello,

I've been using Cayenne and allowing for changing backends at runtime-- 
representing the same schema in MySQL, Oracle, Apache Derby, and have  
had success changing the backend with:

             DataSource dataSource = new PoolManager(
                     jdbcDriverDetails.getDriverClass(),
                     myURL,
                     1,
                     5,
                     myUser,
                     myPassword);
             Configuration config =  
Configuration.getSharedConfiguration();
             DataDomain domain = config.getDomain();
             DataNode node = domain.getNode("MyDomain");
             node.setDataSource(dataSource);

My problem is that I need to also allow a user to select the schema  
that the datamap should be applied to. For example, in Oracle, the  
same schema design might be in multiple instances (in my example,  
KTMI3D, KTMI3M, KTMI3X, etc.). I can change these with the modeler and  
have it work, but I need to change it at runtime. I've tried changing  
it with:

             dataMap.setDefaultSchema(schema);

But haven't had much luck changing at runtime. Is there some way to do  
this with my approach, or is there a better approach to take if you  
want to switch back-ends multiple time at runtime?

Thanks for reading,

Lawrence



Single table inheritance and field hiding

Posted by Marcin Skladaniec <ma...@ish.com.au>.
Hi
I have created a schema with single table inheritance.
It looks something like this: 'Product' is the table, 
database entity, and abstract object entity. There are few 
subclasses of the Product, each has its own unique 
attributes and relationships.

Product:
id
name
description
type (Article, Membership etc.)

Article
weight

Membership:
expiryDays

since all the attributes are defined in the same DbEntity 
CayenneModeller by default put them all into Product 
ObjEntity. I wanted to hide them in the superclass, so I 
moved to relevant ObjEntities. Cayenne does not complain 
when creating records.
If I then execute a simple paged query it works properly:
[java] 07 Jan 2009 19:15:40,619 [btpool0-0       ] INFO 
 org.apache.cayenne.access.QueryLogger :357 - SELECT t0.id 
FROM Product t0 WHERE (t0.isDeleted IS NULL) OR 
(t0.isDeleted = ?) OR (t0.type = ?) OR (t0.type = ?) OR 
(t0.type = ?) ORDER BY t0.name [bind: 1->isDeleted:0, 
2->type:1, 3->type:2, 4->type:3]
      [java] 07 Jan 2009 19:15:40,629 [btpool0-0       ] 
INFO  org.apache.cayenne.access.QueryLogger :401 - === 
returned 1 row. - took 16 ms.
      [java] 07 Jan 2009 19:15:40,629 [btpool0-0       ] 
INFO  org.apache.cayenne.access.QueryLogger :434 - +++ 
transaction committed.


but once the record is about to be faulted it fails
      [java] 07 Jan 2009 19:15:40,635 [btpool0-0       ] 
INFO  org.apache.cayenne.access.QueryLogger :357 - SELECT 
t0.id, t0.modifiedOn, t0.type, t0.notes, t0.isDeleted, 
t0.isWebVisible, t0.willowId, t0.incomeAccountId, 
t0.description, t0.taxId, t0.isOnSale, t0.priceExTax, 
t0.createdOn, t0.name, t0.SKU, t0.weight, t0.expiryDays, 
t0.expiryType, t0.value, t0.liabilityAccountId FROM 
Product t0 WHERE (t0.id = ?) AND ((t0.isDeleted IS NULL) 
OR (t0.isDeleted = ?) OR (t0.type = ?) OR (t0.type = ?) OR 
(t0.type = ?)) [bind: 1->id:200, 2->isDeleted:0, 
3->type:1, 4->type:2, 5->type:3]
      [java] 07 Jan 2009 19:15:40,666 [btpool0-0       ] 
INFO  org.apache.cayenne.access.QueryLogger :453 - *** 
error.
      [java] java.lang.NullPointerException
      [java] 	at 
org.apache.cayenne.exp.parser.SimpleNode.evaluateChild(SimpleNode.java:315)
      [java] 	at 
org.apache.cayenne.exp.parser.ASTEqual.evaluateNode(ASTEqual.java:61)
      [java] 	at 
org.apache.cayenne.exp.parser.SimpleNode.evaluate(SimpleNode.java:327)
      [java] 	at 
org.apache.cayenne.exp.parser.SimpleNode.evaluateChild(SimpleNode.java:315)
      [java] 	at 
org.apache.cayenne.exp.parser.ASTOr.evaluateNode(ASTOr.java:69)
      [java] 	at 
org.apache.cayenne.exp.parser.SimpleNode.evaluate(SimpleNode.java:327)
      [java] 	at 
org.apache.cayenne.exp.Expression.match(Expression.java:367)
      [java] 	at 
org.apache.cayenne.map.EntityInheritanceTree.entityMatchingRow(EntityInheritanceTree.java:92)
      [java] 	at 
org.apache.cayenne.access.jdbc.DataRowPostProcessor.getOverrides(DataRowPostProcessor.java:147)
      [java] 	at 
org.apache.cayenne.access.jdbc.DataRowPostProcessor.postprocessRow(DataRowPostProcessor.java:128)
      [java] 	at 
org.apache.cayenne.access.jdbc.InheritanceAwareRowReader.postprocessRow(InheritanceAwareRowReader.java:45)
      [java] 	at 
org.apache.cayenne.access.jdbc.FullRowReader.readRow(FullRowReader.java:54)
      [java] 	at 
org.apache.cayenne.access.jdbc.FullRowReader.readRow(FullRowReader.java:31)
      [java] 	at 
org.apache.cayenne.access.jdbc.JDBCResultIterator.nextRow(JDBCResultIterator.java:194)
      [java] 	at 
org.apache.cayenne.access.jdbc.JDBCResultIterator.allRows(JDBCResultIterator.java:171)
      [java] 	at 
org.apache.cayenne.access.jdbc.SelectAction.performAction(SelectAction.java:155)
      [java] 	at 
org.apache.cayenne.access.DataNodeQueryAction.runQuery(DataNodeQueryAction.java:87)
      [java] 	at 
org.apache.cayenne.access.DataNode.performQueries(DataNode.java:236)
      [java] 	at 
org.apache.cayenne.access.DataDomainQueryAction.runQuery(DataDomainQueryAction.java:422)
      [java] 	at 
org.apache.cayenne.access.DataDomainQueryAction.access$000(DataDomainQueryAction.java:66)
      [java] 	at 
org.apache.cayenne.access.DataDomainQueryAction$2.transform(DataDomainQueryAction.java:395)
      [java] 	at 
org.apache.cayenne.access.DataDomain.runInTransaction(DataDomain.java:846)
      [java] 	at 
org.apache.cayenne.access.DataDomainQueryAction.runQueryInTransaction(DataDomainQueryAction.java:392)
      [java] 	at 
org.apache.cayenne.access.DataDomainQueryAction.execute(DataDomainQueryAction.java:118)
      [java] 	at 
org.apache.cayenne.access.DataDomain.onQuery(DataDomain.java:739)
      [java] 	at 
org.apache.cayenne.util.ObjectContextQueryAction.runQuery(ObjectContextQueryAction.java:316)
      [java] 	at 
org.apache.cayenne.util.ObjectContextQueryAction.execute(ObjectContextQueryAction.java:95)
      [java] 	at 
org.apache.cayenne.access.DataContext.onQuery(DataContext.java:1267)
      [java] 	at 
org.apache.cayenne.access.DataContext.performQuery(DataContext.java:1256)
      [java] 	at 
org.apache.cayenne.access.IncrementalFaultList.resolveInterval(IncrementalFaultList.java:295)
      [java] 	at 
org.apache.cayenne.access.IncrementalFaultList.get(IncrementalFaultList.java:550)
      [java] 	at 
org.apache.cayenne.access.IncrementalFaultList$1.next(IncrementalFaultList.java:467)
      [java] 	at 
org.apache.cayenne.access.ClientServerChannelQueryAction.toClientObjects(ClientServerChannelQueryAction.java:187)

Is my design correct? can I hide the attributes from the 
superclass and expose them only in the subclass?
Thanks
Marcin


Re: Changing database schemas at runtime

Posted by Lawrence Gerstley <la...@gmail.com>.
This worked great. Thanks for the tip.

     public boolean setDataMapSchema(DataMap dataMap, String schema) {
         try {
             for (DbEntity dbEntity : dataMap.getDbEntities()) {
                 dbEntity.setSchema(schema);
             }
         } catch (Exception e) {
             System.out.println(e.toString());
             return false;
         }
         return true;
     }

Lawrence


On Jan 5, 2009, at 11:11 PM, Andrus Adamchik wrote:

> Hi Lawrence,
>
> Yeah, the "default schema" is ignored in runtime, and only per  
> DbEntity schema is consulted. Looking back, it would've been better  
> to use the default if DbEntity schema is not set, and we may change  
> the behavior at some point, but for now "default schema" is only  
> used by the Modeler.
>
> So to change schema you would need to iterate through all DbEntities  
> and set it per entity.
>
> Andrus
>
> On Jan 6, 2009, at 3:57 AM, Lawrence Gerstley wrote:
>
>> Hello,
>>
>> I've been using Cayenne and allowing for changing backends at  
>> runtime--representing the same schema in MySQL, Oracle, Apache  
>> Derby, and have had success changing the backend with:
>>
>>           DataSource dataSource = new PoolManager(
>>                   jdbcDriverDetails.getDriverClass(),
>>                   myURL,
>>                   1,
>>                   5,
>>                   myUser,
>>                   myPassword);
>>           Configuration config =  
>> Configuration.getSharedConfiguration();
>>           DataDomain domain = config.getDomain();
>>           DataNode node = domain.getNode("MyDomain");
>>           node.setDataSource(dataSource);
>>
>> My problem is that I need to also allow a user to select the schema  
>> that the datamap should be applied to. For example, in Oracle, the  
>> same schema design might be in multiple instances (in my example,  
>> KTMI3D, KTMI3M, KTMI3X, etc.). I can change these with the modeler  
>> and have it work, but I need to change it at runtime. I've tried  
>> changing it with:
>>
>>           dataMap.setDefaultSchema(schema);
>>
>> But haven't had much luck changing at runtime. Is there some way to  
>> do this with my approach, or is there a better approach to take if  
>> you want to switch back-ends multiple time at runtime?
>>
>> Thanks for reading,
>>
>> Lawrence
>>
>>
>


Re: Changing database schemas at runtime

Posted by Andrus Adamchik <an...@objectstyle.org>.
Hi Lawrence,

Yeah, the "default schema" is ignored in runtime, and only per  
DbEntity schema is consulted. Looking back, it would've been better to  
use the default if DbEntity schema is not set, and we may change the  
behavior at some point, but for now "default schema" is only used by  
the Modeler.

So to change schema you would need to iterate through all DbEntities  
and set it per entity.

Andrus

On Jan 6, 2009, at 3:57 AM, Lawrence Gerstley wrote:

> Hello,
>
> I've been using Cayenne and allowing for changing backends at  
> runtime--representing the same schema in MySQL, Oracle, Apache  
> Derby, and have had success changing the backend with:
>
>            DataSource dataSource = new PoolManager(
>                    jdbcDriverDetails.getDriverClass(),
>                    myURL,
>                    1,
>                    5,
>                    myUser,
>                    myPassword);
>            Configuration config =  
> Configuration.getSharedConfiguration();
>            DataDomain domain = config.getDomain();
>            DataNode node = domain.getNode("MyDomain");
>            node.setDataSource(dataSource);
>
> My problem is that I need to also allow a user to select the schema  
> that the datamap should be applied to. For example, in Oracle, the  
> same schema design might be in multiple instances (in my example,  
> KTMI3D, KTMI3M, KTMI3X, etc.). I can change these with the modeler  
> and have it work, but I need to change it at runtime. I've tried  
> changing it with:
>
>            dataMap.setDefaultSchema(schema);
>
> But haven't had much luck changing at runtime. Is there some way to  
> do this with my approach, or is there a better approach to take if  
> you want to switch back-ends multiple time at runtime?
>
> Thanks for reading,
>
> Lawrence
>
>