You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@cayenne.apache.org by Mike Kienenberger <mk...@gmail.com> on 2014/01/01 16:36:48 UTC

Changes (probably between 1.1 and 1.2) in how Cayenne handles fetching relationships (overzealous now)

In the old days (1.1), a relationship to a table that didn't exist in
the current database and wasn't referenced explicitly by the java code
wasn't an issue.  But after my upgrade to 1.2/2.0/3.0 ending at 3.1, I
noticed that cayenne would generate relationship queries for these
items even when they were not necessary.

For awhile, I was able to deal with this by explicitly checking for
known "bad" relationships by detecting them and returning null.

public Query willPerformQuery(DataContext dataContext, Query query) {

        if (query instanceof RelationshipQuery) {
            RelationshipQuery relationshipQuery = (RelationshipQuery)query;
            if (we_know_the_relationships_are_not_used_by_this_deployment) {
                if
("Account".equals(relationshipQuery.getObjectId().getEntityName())) {
                    if
("accountBadRelationshipNameForThisDeployment".equals(relationshipQuery.getRelationshipName()))
{
                        // do nothing
                        return null;
                    }
                }

But then I started to hit them for relationships being internally
generated by Cayenne, which is even more frustrating as these are now
relationships not used by any of my code in any situation, and I can't
detect them and ignore them any more.

It seems rather odd to me that we are executing database queries
against relationships which the end-user doesn't even define as an
ObjRelationship.

I am probably going to just create a separate datamap for each
deployment type (there are currently only two) rather than fight this
any more.   The timing is somewhat right as the application originally
ran at two divisions of the same company, and those have now split
into two separate companies and there is a desire to maintain the code
separately.   But it still seems as if this is a problem that Cayenne
should not be creating and has performance and efficiency issues.


Ebpp DEBUG [btpool0-14 01-01 10:09:28]
RestrictingQualifierDataContextDelegate: in
RestrictingQualifierDataContextDelegate.willPerformQuery(DataContext,
Query)
Ebpp DEBUG [btpool0-14 01-01 10:09:28]
RestrictingQualifierDataContextDelegate:
relationshipQuery.getRelationshipName()=runtimeRelationship2
Ebpp DEBUG [btpool0-14 01-01 10:09:28]
RestrictingQualifierDataContextDelegate:
relationshipQuery.getObjectId().getEntityName()=Account
Ebpp INFO  [btpool0-14 01-01 10:09:28] CommonsJdbcEventLogger: ---
transaction started.

Ebpp INFO  [btpool0-14 01-01 10:09:28] CommonsJdbcEventLogger: SELECT
DISTINCT t0.ALTITUDE AS c0, t0.DOOR_HANGER_NUMBER AS c1,
t0.INVALIDATED AS c2, t0.INVALIDATED_DATE AS c3,
t0.IS_ADDED_TO_MAP_DATABASE AS c4, t0.LATITUDE AS c5, t0.LONGITUDE AS
c6, t0.ID AS c7, t0.SERVICE_ADDRESS_ID AS c8, t0.TAX_DISTRICT_ID AS c9
FROM PREMISE t0 JOIN ACCOUNT_THISTABLEDOESNOTEXIST t1 ON (t0.ID =
t1.PREMISE_ID) WHERE t1.ID = ? [bind: 1:58401]
Ebpp INFO  [btpool0-14 01-01 10:09:28] CommonsJdbcEventLogger: *** error.
java.sql.SQLException: ORA-00942: table or view does not exist
[...]
    at org.apache.cayenne.access.jdbc.SelectAction.performAction(SelectAction.java:75)
    at org.apache.cayenne.access.DataNodeQueryAction.runQuery(DataNodeQueryAction.java:87)
    at org.apache.cayenne.access.DataNode.performQueries(DataNode.java:280)
    at org.apache.cayenne.access.DataDomainQueryAction.runQuery(DataDomainQueryAction.java:442)
    at org.apache.cayenne.access.DataDomainQueryAction.access$000(DataDomainQueryAction.java:70)
    at org.apache.cayenne.access.DataDomainQueryAction$2.transform(DataDomainQueryAction.java:415)
    at org.apache.cayenne.access.DataDomain.runInTransaction(DataDomain.java:877)
    at org.apache.cayenne.access.DataDomainQueryAction.runQueryInTransaction(DataDomainQueryAction.java:412)
    at org.apache.cayenne.access.DataDomainQueryAction.execute(DataDomainQueryAction.java:122)
    at org.apache.cayenne.access.DataDomain.onQueryNoFilters(DataDomain.java:758)
    at org.apache.cayenne.access.DataDomain$DataDomainQueryFilterChain.onQuery(DataDomain.java:1009)
    at org.apache.cayenne.access.DataDomain.onQuery(DataDomain.java:748)
    at org.apache.cayenne.util.ObjectContextQueryAction.runQuery(ObjectContextQueryAction.java:350)
    at org.apache.cayenne.util.ObjectContextQueryAction.executePostCache(ObjectContextQueryAction.java:106)
    at org.apache.cayenne.util.ObjectContextQueryAction.execute(ObjectContextQueryAction.java:93)
    at org.apache.cayenne.access.DataContext.onQuery(DataContext.java:989)
    at org.apache.cayenne.access.DataContext.performQuery(DataContext.java:978)
    at org.apache.cayenne.access.ToOneFault.doResolveFault(ToOneFault.java:81)
    at org.apache.cayenne.access.ToOneFault.resolveFault(ToOneFault.java:54)
    at org.apache.cayenne.CayenneDataObject.readProperty(CayenneDataObject.java:186)
    at org.apache.cayenne.reflect.generic.DataObjectBaseProperty.readProperty(DataObjectBaseProperty.java:43)
    at org.apache.cayenne.access.ObjectDiff$1.visitToOne(ObjectDiff.java:106)
    at org.apache.cayenne.reflect.generic.DataObjectToOneProperty.visit(DataObjectToOneProperty.java:87)
    at org.apache.cayenne.reflect.PersistentDescriptor.visitProperties(PersistentDescriptor.java:411)
    at org.apache.cayenne.reflect.LazyClassDescriptorDecorator.visitProperties(LazyClassDescriptorDecorator.java:174)
    at org.apache.cayenne.access.ObjectDiff.<init>(ObjectDiff.java:92)
    at org.apache.cayenne.access.ObjectStore.registerDiff(ObjectStore.java:224)
    at org.apache.cayenne.access.ObjectStore.arcCreated(ObjectStore.java:983)
    at org.apache.cayenne.util.ObjectContextGraphAction.handleArcPropertyChange(ObjectContextGraphAction.java:88)
    at org.apache.cayenne.util.ObjectContextGraphAction.handlePropertyChange(ObjectContextGraphAction.java:65)
    at org.apache.cayenne.BaseContext.propertyChanged(BaseContext.java:477)
    at org.apache.cayenne.CayenneDataObject.addToManyTarget(CayenneDataObject.java:251)
    at org.apache.cayenne.CayenneDataObject.setReverseRelationship(CayenneDataObject.java:337)
    at org.apache.cayenne.CayenneDataObject.setToOneTarget(CayenneDataObject.java:288)
    at com.xyz.cayenne.ebpp.entity.generated._ScheduledPayment.setAccount(_ScheduledPayment.java:736)

Re: Changes (probably between 1.1 and 1.2) in how Cayenne handles fetching relationships (overzealous now)

Posted by Andrus Adamchik <an...@objectstyle.org>.
On Jan 2, 2014, at 4:47 PM, Mike Kienenberger <mk...@gmail.com> wrote:

> But even without the runtime relationships, we still have a
> over-zealous fetching algorithm.   If I get a chance, I'll try looking
> into it again to see what is triggering it.

This was another thing I was going to comment on. Older Cayenne was much more naive about returning a HOLLOW object without checking whether such object is present in the DB or not. As we went on fixing various bugs coming from it, it became “over-zealous” and more correct. Check DataDomainQueryAction.interceptRelationshipQuery, and specifically relationship.isSourceDefiningTargetPrecenseAndType call in it.

Andrus


Re: Changes (probably between 1.1 and 1.2) in how Cayenne handles fetching relationships (overzealous now)

Posted by Mike Kienenberger <mk...@gmail.com>.
I'll take a look at upgrading to trunk.

But even without the runtime relationships, we still have a
over-zealous fetching algorithm.   If I get a chance, I'll try looking
into it again to see what is triggering it.

It'll be awhile as I have a lot of velocity templates to upgrade from
pre-1.2 to now since I've made massive changes to my database model,
and a lot of code to remove.


On Thu, Jan 2, 2014 at 5:14 AM, Andrus Adamchik <an...@objectstyle.org> wrote:
> One source of constant trouble introduced in 3.0 is “runtime” relationships. We finally got rid of them on trunk (CAY-1861). Perhaps you may try it with a trunk build and see if that helps?
>
> Andrus
>
>
> On Jan 1, 2014, at 6:36 PM, Mike Kienenberger <mk...@gmail.com> wrote:
>
>> In the old days (1.1), a relationship to a table that didn't exist in
>> the current database and wasn't referenced explicitly by the java code
>> wasn't an issue.  But after my upgrade to 1.2/2.0/3.0 ending at 3.1, I
>> noticed that cayenne would generate relationship queries for these
>> items even when they were not necessary.
>>
>> For awhile, I was able to deal with this by explicitly checking for
>> known "bad" relationships by detecting them and returning null.
>>
>> public Query willPerformQuery(DataContext dataContext, Query query) {
>>
>>        if (query instanceof RelationshipQuery) {
>>            RelationshipQuery relationshipQuery = (RelationshipQuery)query;
>>            if (we_know_the_relationships_are_not_used_by_this_deployment) {
>>                if
>> ("Account".equals(relationshipQuery.getObjectId().getEntityName())) {
>>                    if
>> ("accountBadRelationshipNameForThisDeployment".equals(relationshipQuery.getRelationshipName()))
>> {
>>                        // do nothing
>>                        return null;
>>                    }
>>                }
>>
>> But then I started to hit them for relationships being internally
>> generated by Cayenne, which is even more frustrating as these are now
>> relationships not used by any of my code in any situation, and I can't
>> detect them and ignore them any more.
>>
>> It seems rather odd to me that we are executing database queries
>> against relationships which the end-user doesn't even define as an
>> ObjRelationship.
>>
>> I am probably going to just create a separate datamap for each
>> deployment type (there are currently only two) rather than fight this
>> any more.   The timing is somewhat right as the application originally
>> ran at two divisions of the same company, and those have now split
>> into two separate companies and there is a desire to maintain the code
>> separately.   But it still seems as if this is a problem that Cayenne
>> should not be creating and has performance and efficiency issues.
>>
>>
>> Ebpp DEBUG [btpool0-14 01-01 10:09:28]
>> RestrictingQualifierDataContextDelegate: in
>> RestrictingQualifierDataContextDelegate.willPerformQuery(DataContext,
>> Query)
>> Ebpp DEBUG [btpool0-14 01-01 10:09:28]
>> RestrictingQualifierDataContextDelegate:
>> relationshipQuery.getRelationshipName()=runtimeRelationship2
>> Ebpp DEBUG [btpool0-14 01-01 10:09:28]
>> RestrictingQualifierDataContextDelegate:
>> relationshipQuery.getObjectId().getEntityName()=Account
>> Ebpp INFO  [btpool0-14 01-01 10:09:28] CommonsJdbcEventLogger: ---
>> transaction started.
>>
>> Ebpp INFO  [btpool0-14 01-01 10:09:28] CommonsJdbcEventLogger: SELECT
>> DISTINCT t0.ALTITUDE AS c0, t0.DOOR_HANGER_NUMBER AS c1,
>> t0.INVALIDATED AS c2, t0.INVALIDATED_DATE AS c3,
>> t0.IS_ADDED_TO_MAP_DATABASE AS c4, t0.LATITUDE AS c5, t0.LONGITUDE AS
>> c6, t0.ID AS c7, t0.SERVICE_ADDRESS_ID AS c8, t0.TAX_DISTRICT_ID AS c9
>> FROM PREMISE t0 JOIN ACCOUNT_THISTABLEDOESNOTEXIST t1 ON (t0.ID =
>> t1.PREMISE_ID) WHERE t1.ID = ? [bind: 1:58401]
>> Ebpp INFO  [btpool0-14 01-01 10:09:28] CommonsJdbcEventLogger: *** error.
>> java.sql.SQLException: ORA-00942: table or view does not exist
>> [...]
>>    at org.apache.cayenne.access.jdbc.SelectAction.performAction(SelectAction.java:75)
>>    at org.apache.cayenne.access.DataNodeQueryAction.runQuery(DataNodeQueryAction.java:87)
>>    at org.apache.cayenne.access.DataNode.performQueries(DataNode.java:280)
>>    at org.apache.cayenne.access.DataDomainQueryAction.runQuery(DataDomainQueryAction.java:442)
>>    at org.apache.cayenne.access.DataDomainQueryAction.access$000(DataDomainQueryAction.java:70)
>>    at org.apache.cayenne.access.DataDomainQueryAction$2.transform(DataDomainQueryAction.java:415)
>>    at org.apache.cayenne.access.DataDomain.runInTransaction(DataDomain.java:877)
>>    at org.apache.cayenne.access.DataDomainQueryAction.runQueryInTransaction(DataDomainQueryAction.java:412)
>>    at org.apache.cayenne.access.DataDomainQueryAction.execute(DataDomainQueryAction.java:122)
>>    at org.apache.cayenne.access.DataDomain.onQueryNoFilters(DataDomain.java:758)
>>    at org.apache.cayenne.access.DataDomain$DataDomainQueryFilterChain.onQuery(DataDomain.java:1009)
>>    at org.apache.cayenne.access.DataDomain.onQuery(DataDomain.java:748)
>>    at org.apache.cayenne.util.ObjectContextQueryAction.runQuery(ObjectContextQueryAction.java:350)
>>    at org.apache.cayenne.util.ObjectContextQueryAction.executePostCache(ObjectContextQueryAction.java:106)
>>    at org.apache.cayenne.util.ObjectContextQueryAction.execute(ObjectContextQueryAction.java:93)
>>    at org.apache.cayenne.access.DataContext.onQuery(DataContext.java:989)
>>    at org.apache.cayenne.access.DataContext.performQuery(DataContext.java:978)
>>    at org.apache.cayenne.access.ToOneFault.doResolveFault(ToOneFault.java:81)
>>    at org.apache.cayenne.access.ToOneFault.resolveFault(ToOneFault.java:54)
>>    at org.apache.cayenne.CayenneDataObject.readProperty(CayenneDataObject.java:186)
>>    at org.apache.cayenne.reflect.generic.DataObjectBaseProperty.readProperty(DataObjectBaseProperty.java:43)
>>    at org.apache.cayenne.access.ObjectDiff$1.visitToOne(ObjectDiff.java:106)
>>    at org.apache.cayenne.reflect.generic.DataObjectToOneProperty.visit(DataObjectToOneProperty.java:87)
>>    at org.apache.cayenne.reflect.PersistentDescriptor.visitProperties(PersistentDescriptor.java:411)
>>    at org.apache.cayenne.reflect.LazyClassDescriptorDecorator.visitProperties(LazyClassDescriptorDecorator.java:174)
>>    at org.apache.cayenne.access.ObjectDiff.<init>(ObjectDiff.java:92)
>>    at org.apache.cayenne.access.ObjectStore.registerDiff(ObjectStore.java:224)
>>    at org.apache.cayenne.access.ObjectStore.arcCreated(ObjectStore.java:983)
>>    at org.apache.cayenne.util.ObjectContextGraphAction.handleArcPropertyChange(ObjectContextGraphAction.java:88)
>>    at org.apache.cayenne.util.ObjectContextGraphAction.handlePropertyChange(ObjectContextGraphAction.java:65)
>>    at org.apache.cayenne.BaseContext.propertyChanged(BaseContext.java:477)
>>    at org.apache.cayenne.CayenneDataObject.addToManyTarget(CayenneDataObject.java:251)
>>    at org.apache.cayenne.CayenneDataObject.setReverseRelationship(CayenneDataObject.java:337)
>>    at org.apache.cayenne.CayenneDataObject.setToOneTarget(CayenneDataObject.java:288)
>>    at com.xyz.cayenne.ebpp.entity.generated._ScheduledPayment.setAccount(_ScheduledPayment.java:736)
>>
>

Re: Changes (probably between 1.1 and 1.2) in how Cayenne handles fetching relationships (overzealous now)

Posted by Andrus Adamchik <an...@objectstyle.org>.
One source of constant trouble introduced in 3.0 is “runtime” relationships. We finally got rid of them on trunk (CAY-1861). Perhaps you may try it with a trunk build and see if that helps?

Andrus


On Jan 1, 2014, at 6:36 PM, Mike Kienenberger <mk...@gmail.com> wrote:

> In the old days (1.1), a relationship to a table that didn't exist in
> the current database and wasn't referenced explicitly by the java code
> wasn't an issue.  But after my upgrade to 1.2/2.0/3.0 ending at 3.1, I
> noticed that cayenne would generate relationship queries for these
> items even when they were not necessary.
> 
> For awhile, I was able to deal with this by explicitly checking for
> known "bad" relationships by detecting them and returning null.
> 
> public Query willPerformQuery(DataContext dataContext, Query query) {
> 
>        if (query instanceof RelationshipQuery) {
>            RelationshipQuery relationshipQuery = (RelationshipQuery)query;
>            if (we_know_the_relationships_are_not_used_by_this_deployment) {
>                if
> ("Account".equals(relationshipQuery.getObjectId().getEntityName())) {
>                    if
> ("accountBadRelationshipNameForThisDeployment".equals(relationshipQuery.getRelationshipName()))
> {
>                        // do nothing
>                        return null;
>                    }
>                }
> 
> But then I started to hit them for relationships being internally
> generated by Cayenne, which is even more frustrating as these are now
> relationships not used by any of my code in any situation, and I can't
> detect them and ignore them any more.
> 
> It seems rather odd to me that we are executing database queries
> against relationships which the end-user doesn't even define as an
> ObjRelationship.
> 
> I am probably going to just create a separate datamap for each
> deployment type (there are currently only two) rather than fight this
> any more.   The timing is somewhat right as the application originally
> ran at two divisions of the same company, and those have now split
> into two separate companies and there is a desire to maintain the code
> separately.   But it still seems as if this is a problem that Cayenne
> should not be creating and has performance and efficiency issues.
> 
> 
> Ebpp DEBUG [btpool0-14 01-01 10:09:28]
> RestrictingQualifierDataContextDelegate: in
> RestrictingQualifierDataContextDelegate.willPerformQuery(DataContext,
> Query)
> Ebpp DEBUG [btpool0-14 01-01 10:09:28]
> RestrictingQualifierDataContextDelegate:
> relationshipQuery.getRelationshipName()=runtimeRelationship2
> Ebpp DEBUG [btpool0-14 01-01 10:09:28]
> RestrictingQualifierDataContextDelegate:
> relationshipQuery.getObjectId().getEntityName()=Account
> Ebpp INFO  [btpool0-14 01-01 10:09:28] CommonsJdbcEventLogger: ---
> transaction started.
> 
> Ebpp INFO  [btpool0-14 01-01 10:09:28] CommonsJdbcEventLogger: SELECT
> DISTINCT t0.ALTITUDE AS c0, t0.DOOR_HANGER_NUMBER AS c1,
> t0.INVALIDATED AS c2, t0.INVALIDATED_DATE AS c3,
> t0.IS_ADDED_TO_MAP_DATABASE AS c4, t0.LATITUDE AS c5, t0.LONGITUDE AS
> c6, t0.ID AS c7, t0.SERVICE_ADDRESS_ID AS c8, t0.TAX_DISTRICT_ID AS c9
> FROM PREMISE t0 JOIN ACCOUNT_THISTABLEDOESNOTEXIST t1 ON (t0.ID =
> t1.PREMISE_ID) WHERE t1.ID = ? [bind: 1:58401]
> Ebpp INFO  [btpool0-14 01-01 10:09:28] CommonsJdbcEventLogger: *** error.
> java.sql.SQLException: ORA-00942: table or view does not exist
> [...]
>    at org.apache.cayenne.access.jdbc.SelectAction.performAction(SelectAction.java:75)
>    at org.apache.cayenne.access.DataNodeQueryAction.runQuery(DataNodeQueryAction.java:87)
>    at org.apache.cayenne.access.DataNode.performQueries(DataNode.java:280)
>    at org.apache.cayenne.access.DataDomainQueryAction.runQuery(DataDomainQueryAction.java:442)
>    at org.apache.cayenne.access.DataDomainQueryAction.access$000(DataDomainQueryAction.java:70)
>    at org.apache.cayenne.access.DataDomainQueryAction$2.transform(DataDomainQueryAction.java:415)
>    at org.apache.cayenne.access.DataDomain.runInTransaction(DataDomain.java:877)
>    at org.apache.cayenne.access.DataDomainQueryAction.runQueryInTransaction(DataDomainQueryAction.java:412)
>    at org.apache.cayenne.access.DataDomainQueryAction.execute(DataDomainQueryAction.java:122)
>    at org.apache.cayenne.access.DataDomain.onQueryNoFilters(DataDomain.java:758)
>    at org.apache.cayenne.access.DataDomain$DataDomainQueryFilterChain.onQuery(DataDomain.java:1009)
>    at org.apache.cayenne.access.DataDomain.onQuery(DataDomain.java:748)
>    at org.apache.cayenne.util.ObjectContextQueryAction.runQuery(ObjectContextQueryAction.java:350)
>    at org.apache.cayenne.util.ObjectContextQueryAction.executePostCache(ObjectContextQueryAction.java:106)
>    at org.apache.cayenne.util.ObjectContextQueryAction.execute(ObjectContextQueryAction.java:93)
>    at org.apache.cayenne.access.DataContext.onQuery(DataContext.java:989)
>    at org.apache.cayenne.access.DataContext.performQuery(DataContext.java:978)
>    at org.apache.cayenne.access.ToOneFault.doResolveFault(ToOneFault.java:81)
>    at org.apache.cayenne.access.ToOneFault.resolveFault(ToOneFault.java:54)
>    at org.apache.cayenne.CayenneDataObject.readProperty(CayenneDataObject.java:186)
>    at org.apache.cayenne.reflect.generic.DataObjectBaseProperty.readProperty(DataObjectBaseProperty.java:43)
>    at org.apache.cayenne.access.ObjectDiff$1.visitToOne(ObjectDiff.java:106)
>    at org.apache.cayenne.reflect.generic.DataObjectToOneProperty.visit(DataObjectToOneProperty.java:87)
>    at org.apache.cayenne.reflect.PersistentDescriptor.visitProperties(PersistentDescriptor.java:411)
>    at org.apache.cayenne.reflect.LazyClassDescriptorDecorator.visitProperties(LazyClassDescriptorDecorator.java:174)
>    at org.apache.cayenne.access.ObjectDiff.<init>(ObjectDiff.java:92)
>    at org.apache.cayenne.access.ObjectStore.registerDiff(ObjectStore.java:224)
>    at org.apache.cayenne.access.ObjectStore.arcCreated(ObjectStore.java:983)
>    at org.apache.cayenne.util.ObjectContextGraphAction.handleArcPropertyChange(ObjectContextGraphAction.java:88)
>    at org.apache.cayenne.util.ObjectContextGraphAction.handlePropertyChange(ObjectContextGraphAction.java:65)
>    at org.apache.cayenne.BaseContext.propertyChanged(BaseContext.java:477)
>    at org.apache.cayenne.CayenneDataObject.addToManyTarget(CayenneDataObject.java:251)
>    at org.apache.cayenne.CayenneDataObject.setReverseRelationship(CayenneDataObject.java:337)
>    at org.apache.cayenne.CayenneDataObject.setToOneTarget(CayenneDataObject.java:288)
>    at com.xyz.cayenne.ebpp.entity.generated._ScheduledPayment.setAccount(_ScheduledPayment.java:736)
>