You are viewing a plain text version of this content. The canonical link for it is here.
Posted to user@cayenne.apache.org by Mathias Clerc <tl...@gmail.com> on 2010/10/15 06:20:31 UTC

Context question

Hello,

I am making an evaluation of Cayenne and other frameworks.

One of my test is the following :

begin a set of operations
make a select * on one table
insert new element in that table
make another select * on that table (see that new element along with
the previous results)
rollback
make another select * on that table (see that it came back to it's
original state)


I am using the following code :
        ObjectContext context1 = DataContext.createDataContext();
        SelectQuery querySelectAll = new SelectQuery(Principal.class);
        System.out.println("-test pre");
        for (Object out : context1.performQuery(querySelectAll)) {
            System.out.println(((Principal) out).getName());
        }

        Principal newPrincipal = context1.newObject(Principal.class);
        newPrincipal.setName("toto");
        context1.registerNewObject(newPrincipal); //Same with or
without this line

        SelectQuery querySelectAll2 = new SelectQuery(Principal.class);
        System.out.println("-test post");
        System.out.println("--c1");
        for (Object out : context1.performQuery(querySelectAll2)) {
            System.out.println(((Principal) out).getName());
        }
        System.out.println("--new context");
        for (Object out :
DataContext.createDataContext().performQuery(querySelectAll2)) {
            System.out.println(((Principal) out).getName());
        }

        context1.rollbackChanges();
        System.out.println("-test post rollback");
        SelectQuery querySelectAll3 = new SelectQuery(Principal.class);
        System.out.println("--c1");
        for (Object out : context1.performQuery(querySelectAll3)) {
            System.out.println(((Principal) out).getName());
        }
        System.out.println("--new context");
        for (Object out :
DataContext.createDataContext().performQuery(querySelectAll3)) {
            System.out.println(((Principal) out).getName());
        }

And the output is :
-test pre
domain
administrators
admin
-test post
--c1
domain
administrators
admin
--new context
domain
administrators
admin
-test post rollback
--c1
domain
administrators
admin
--new context
domain
administrators
admin

I think I have not understood completely what a context is.
My question is in "test post" "c1" (created new element "toto", not
commited, query done in the new element's context) shouldn't my new
element appear ?
If I do a commit on context1 then my element is visible, but it also
hit the table.

In case that behaviour is normal, how can I do some local changes to
the dataset without having to commit them to the database ?

Thank you,

Tlarhices

Re: Context question

Posted by Andrus Adamchik <an...@objectstyle.org>.
On Oct 15, 2010, at 11:24 AM, Andrey Razumovsky wrote:

> 
> The reason of 2) is that Cayenne uses caching of data objects, which greatly
> increases performance. So object is basically the same. You can "refresh"
> the cache using RefreshQuery.


No actually the reason for this is not caching, but the fact that ObjectContext is an isolated view of an object sugbgraph, which can contain only 1 instance of any given object ("uniquing"). So a select that fetches data for the object already in the context will update that object (instead of creating a second copy). On the other hand if such object is modified locally in the context, select will not revert user modification (as an opposite behavior would have been really evil). 

Andrus


Re: Context question

Posted by Andrey Razumovsky <ra...@gmail.com>.
Hi Mathias,

The main reason why 1) and 3) cannot be done is that SelectQuery (and almost
any other fetching query) should support fetch size/limit and paging. This
makes "local" data useless, because we don't know where insert it to.

The reason of 2) is that Cayenne uses caching of data objects, which greatly
increases performance. So object is basically the same. You can "refresh"
the cache using RefreshQuery.

Hope that helps,

2010/10/15 Mathias Clerc <tl...@gmail.com>

> 2010/10/15 Andrey Razumovsky <ra...@gmail.com>:
> > SelectQuery is actually a query to database, so viewing not-yet-inserted
> > objects with it is not possible. See recent discussion:
> >
> http://cayenne.markmail.org/search/%20list:org.apache.cayenne.user#query:%20list%3Aorg.apache.cayenne.user+page:2+mid:6bwqse4t4czj73zq+state:results
>
> Thank you for your answers Borut and Andrey.
>
> I was able to do what I wanted through this hackish way :
>
>    private static List updateContentWithCurrentState(List objects,
> Class<?> objectClass, Expression e,
>            ObjectContext context) {
>        //Add new objects matching the class (limits in hierarchy, see
> isInstance doc)
>        for (Object o : context.newObjects()) {
>            if (objectClass.isInstance(o)) {
>                objects.add(o);
>            }
>        }
>        //Remove any object deleted
>        for (Object o : context.deletedObjects()) {
>            if (objects.contains(o)) {
>                objects.remove(o);
>            }
>        }
>        //Apply filter (to remove non matching objects added at the
> beggining)
>        if (e != null) {
>            objects = e.filterObjects(objects);
>        }
>        return objects;
>    }
>
> Maybe it will not work in all cases, I am still early beginer but for
> my tests it was enough.
>
> I am still puzzled by standard behaviour :
> 1) Doing context.newObject(objectClass) and then selecting doesn't
> show the new object
> 2) Doing a ((MyClass)context.preformQuery().get(0)).setName("new") and
> then selecting will return an object with the new name
> 3) Doingcontext.deleteObject(object) and then selecting still returns
> the original object
>
> In 1) and 3) data is returned as it is in the db, but not in the
> context (DB snapshot)
> In 2) data is returned as it is in the context, but not anymore in the
> db (non DB snapshot)
>
> Quite confusing.
>



-- 
Andrey

Re: Context question

Posted by Andrus Adamchik <an...@objectstyle.org>.
Getting used to ObjectContext may take some time when coming from other ORM backgrounds, but in general most people have a rather smooth ride with it.

While I can theoretically see a value of (optionally?) selecting against uncommitted objects, I've never had a practical case for it in my apps. Which can be attributed to the way how I am designing persistent code with ObjectContext behavior in mind. So... maybe you can explain the problem you are trying to solve, and we can think of a better solution?

Andrus



On Oct 15, 2010, at 11:09 AM, Mathias Clerc wrote:

> 2010/10/15 Andrey Razumovsky <ra...@gmail.com>:
>> SelectQuery is actually a query to database, so viewing not-yet-inserted
>> objects with it is not possible. See recent discussion:
>> http://cayenne.markmail.org/search/%20list:org.apache.cayenne.user#query:%20list%3Aorg.apache.cayenne.user+page:2+mid:6bwqse4t4czj73zq+state:results
> 
> Thank you for your answers Borut and Andrey.
> 
> I was able to do what I wanted through this hackish way :
> 
>    private static List updateContentWithCurrentState(List objects,
> Class<?> objectClass, Expression e,
>            ObjectContext context) {
>        //Add new objects matching the class (limits in hierarchy, see
> isInstance doc)
>        for (Object o : context.newObjects()) {
>            if (objectClass.isInstance(o)) {
>                objects.add(o);
>            }
>        }
>        //Remove any object deleted
>        for (Object o : context.deletedObjects()) {
>            if (objects.contains(o)) {
>                objects.remove(o);
>            }
>        }
>        //Apply filter (to remove non matching objects added at the beggining)
>        if (e != null) {
>            objects = e.filterObjects(objects);
>        }
>        return objects;
>    }
> 
> Maybe it will not work in all cases, I am still early beginer but for
> my tests it was enough.
> 
> I am still puzzled by standard behaviour :
> 1) Doing context.newObject(objectClass) and then selecting doesn't
> show the new object
> 2) Doing a ((MyClass)context.preformQuery().get(0)).setName("new") and
> then selecting will return an object with the new name
> 3) Doingcontext.deleteObject(object) and then selecting still returns
> the original object
> 
> In 1) and 3) data is returned as it is in the db, but not in the
> context (DB snapshot)
> In 2) data is returned as it is in the context, but not anymore in the
> db (non DB snapshot)
> 
> Quite confusing.
> 


Re: Context question

Posted by Mathias Clerc <tl...@gmail.com>.
2010/10/15 Andrey Razumovsky <ra...@gmail.com>:
> SelectQuery is actually a query to database, so viewing not-yet-inserted
> objects with it is not possible. See recent discussion:
> http://cayenne.markmail.org/search/%20list:org.apache.cayenne.user#query:%20list%3Aorg.apache.cayenne.user+page:2+mid:6bwqse4t4czj73zq+state:results

Thank you for your answers Borut and Andrey.

I was able to do what I wanted through this hackish way :

    private static List updateContentWithCurrentState(List objects,
Class<?> objectClass, Expression e,
            ObjectContext context) {
        //Add new objects matching the class (limits in hierarchy, see
isInstance doc)
        for (Object o : context.newObjects()) {
            if (objectClass.isInstance(o)) {
                objects.add(o);
            }
        }
        //Remove any object deleted
        for (Object o : context.deletedObjects()) {
            if (objects.contains(o)) {
                objects.remove(o);
            }
        }
        //Apply filter (to remove non matching objects added at the beggining)
        if (e != null) {
            objects = e.filterObjects(objects);
        }
        return objects;
    }

Maybe it will not work in all cases, I am still early beginer but for
my tests it was enough.

I am still puzzled by standard behaviour :
1) Doing context.newObject(objectClass) and then selecting doesn't
show the new object
2) Doing a ((MyClass)context.preformQuery().get(0)).setName("new") and
then selecting will return an object with the new name
3) Doingcontext.deleteObject(object) and then selecting still returns
the original object

In 1) and 3) data is returned as it is in the db, but not in the
context (DB snapshot)
In 2) data is returned as it is in the context, but not anymore in the
db (non DB snapshot)

Quite confusing.

Re: Context question

Posted by Andrey Razumovsky <ra...@gmail.com>.
SelectQuery is actually a query to database, so viewing not-yet-inserted
objects with it is not possible. See recent discussion:
http://cayenne.markmail.org/search/%20list:org.apache.cayenne.user#query:%20list%3Aorg.apache.cayenne.user+page:2+mid:6bwqse4t4czj73zq+state:results

2010/10/15 Borut Bolčina <bo...@gmail.com>

> Hello Mathias,
>
> context is similar to session in hibernate, but much better. The context is
> where your persistent objects live in any of their possible state (
> http://cayenne.apache.org/doc30/persistent-object-lifecycle.html).
>
> You are trying to rollback database changes made in previous step. This is
> not what context.rollback() does. See last paragraph at
> http://cayenne.apache.org/doc30/dataobject-state-management.html.
>
> When you do context.commit, you hit the database (or cache) if there are
> any
> changes in the object graph you created or modified in the context you are
> trying to commit.
>
> What do you mean by: "How can I do some local changes to the dataset
> without
> having to commit them to the database?"
>
> Cheers,
> Borut
>
> 2010/10/15 Mathias Clerc <tl...@gmail.com>
>
> > Hello,
> >
> > I am making an evaluation of Cayenne and other frameworks.
> >
> > One of my test is the following :
> >
> > begin a set of operations
> > make a select * on one table
> > insert new element in that table
> > make another select * on that table (see that new element along with
> > the previous results)
> > rollback
> > make another select * on that table (see that it came back to it's
> > original state)
> >
> >
> > I am using the following code :
> >        ObjectContext context1 = DataContext.createDataContext();
> >        SelectQuery querySelectAll = new SelectQuery(Principal.class);
> >        System.out.println("-test pre");
> >        for (Object out : context1.performQuery(querySelectAll)) {
> >            System.out.println(((Principal) out).getName());
> >        }
> >
> >        Principal newPrincipal = context1.newObject(Principal.class);
> >        newPrincipal.setName("toto");
> >        context1.registerNewObject(newPrincipal); //Same with or
> > without this line
> >
> >        SelectQuery querySelectAll2 = new SelectQuery(Principal.class);
> >        System.out.println("-test post");
> >        System.out.println("--c1");
> >        for (Object out : context1.performQuery(querySelectAll2)) {
> >            System.out.println(((Principal) out).getName());
> >        }
> >        System.out.println("--new context");
> >        for (Object out :
> > DataContext.createDataContext().performQuery(querySelectAll2)) {
> >            System.out.println(((Principal) out).getName());
> >        }
> >
> >        context1.rollbackChanges();
> >        System.out.println("-test post rollback");
> >        SelectQuery querySelectAll3 = new SelectQuery(Principal.class);
> >        System.out.println("--c1");
> >        for (Object out : context1.performQuery(querySelectAll3)) {
> >            System.out.println(((Principal) out).getName());
> >        }
> >        System.out.println("--new context");
> >        for (Object out :
> > DataContext.createDataContext().performQuery(querySelectAll3)) {
> >            System.out.println(((Principal) out).getName());
> >        }
> >
> > And the output is :
> > -test pre
> > domain
> > administrators
> > admin
> > -test post
> > --c1
> > domain
> > administrators
> > admin
> > --new context
> > domain
> > administrators
> > admin
> > -test post rollback
> > --c1
> > domain
> > administrators
> > admin
> > --new context
> > domain
> > administrators
> > admin
> >
> > I think I have not understood completely what a context is.
> > My question is in "test post" "c1" (created new element "toto", not
> > commited, query done in the new element's context) shouldn't my new
> > element appear ?
> > If I do a commit on context1 then my element is visible, but it also
> > hit the table.
> >
> > In case that behaviour is normal, how can I do some local changes to
> > the dataset without having to commit them to the database ?
> >
> > Thank you,
> >
> > Tlarhices
> >
>



-- 
Andrey

Re: Context question

Posted by Borut Bolčina <bo...@gmail.com>.
Hello Mathias,

context is similar to session in hibernate, but much better. The context is
where your persistent objects live in any of their possible state (
http://cayenne.apache.org/doc30/persistent-object-lifecycle.html).

You are trying to rollback database changes made in previous step. This is
not what context.rollback() does. See last paragraph at
http://cayenne.apache.org/doc30/dataobject-state-management.html.

When you do context.commit, you hit the database (or cache) if there are any
changes in the object graph you created or modified in the context you are
trying to commit.

What do you mean by: "How can I do some local changes to the dataset without
having to commit them to the database?"

Cheers,
Borut

2010/10/15 Mathias Clerc <tl...@gmail.com>

> Hello,
>
> I am making an evaluation of Cayenne and other frameworks.
>
> One of my test is the following :
>
> begin a set of operations
> make a select * on one table
> insert new element in that table
> make another select * on that table (see that new element along with
> the previous results)
> rollback
> make another select * on that table (see that it came back to it's
> original state)
>
>
> I am using the following code :
>        ObjectContext context1 = DataContext.createDataContext();
>        SelectQuery querySelectAll = new SelectQuery(Principal.class);
>        System.out.println("-test pre");
>        for (Object out : context1.performQuery(querySelectAll)) {
>            System.out.println(((Principal) out).getName());
>        }
>
>        Principal newPrincipal = context1.newObject(Principal.class);
>        newPrincipal.setName("toto");
>        context1.registerNewObject(newPrincipal); //Same with or
> without this line
>
>        SelectQuery querySelectAll2 = new SelectQuery(Principal.class);
>        System.out.println("-test post");
>        System.out.println("--c1");
>        for (Object out : context1.performQuery(querySelectAll2)) {
>            System.out.println(((Principal) out).getName());
>        }
>        System.out.println("--new context");
>        for (Object out :
> DataContext.createDataContext().performQuery(querySelectAll2)) {
>            System.out.println(((Principal) out).getName());
>        }
>
>        context1.rollbackChanges();
>        System.out.println("-test post rollback");
>        SelectQuery querySelectAll3 = new SelectQuery(Principal.class);
>        System.out.println("--c1");
>        for (Object out : context1.performQuery(querySelectAll3)) {
>            System.out.println(((Principal) out).getName());
>        }
>        System.out.println("--new context");
>        for (Object out :
> DataContext.createDataContext().performQuery(querySelectAll3)) {
>            System.out.println(((Principal) out).getName());
>        }
>
> And the output is :
> -test pre
> domain
> administrators
> admin
> -test post
> --c1
> domain
> administrators
> admin
> --new context
> domain
> administrators
> admin
> -test post rollback
> --c1
> domain
> administrators
> admin
> --new context
> domain
> administrators
> admin
>
> I think I have not understood completely what a context is.
> My question is in "test post" "c1" (created new element "toto", not
> commited, query done in the new element's context) shouldn't my new
> element appear ?
> If I do a commit on context1 then my element is visible, but it also
> hit the table.
>
> In case that behaviour is normal, how can I do some local changes to
> the dataset without having to commit them to the database ?
>
> Thank you,
>
> Tlarhices
>