Eager vs Lazy produces different results
The group you are posting to is a
Usenet group . Messages posted to this group will make your email address visible to anyone on the Internet.
Your reply message has not been sent.
Your post was successful
From:
Rob Bygrave <robin.bygr... @gmail.com>
Date: Tue, 9 Mar 2010 20:31:58 +1300
Local: Tues, Mar 9 2010 2:31 am
Subject: Re: [ebean] Re: Eager vs Lazy produces different results
> ... or what about that:
> Query<Customer> custQuery = Ebean.find(Customer.class); > custQuery.where().startWith("name", "A");
> Query<Order> custOrderQuery = custQuery.findMany("orders", > Order.class); > custOrderQuery.where().eg("status", Order.Status.NEW).gt("orderDate", > lastWeek);
> But this might be too much work, no?
I don't think this is the right direction in that it is a filter on a joined
*ToMany - so only the expressionList is applicable. Aka I think the 2nd
Query object is not really a good match to the requirement (of filtering
joined *ToMany's.)
Hmmm, that assumes I understood what you meant with this example.
On Mon, Mar 8, 2010 at 8:13 AM, Mario Ivankovits <mario.ivankov... @gmail.com
> wrote:
> Hi!
> > Daryl, Mario ... are you happy to go with Option 2 ?
> Yep, 2 seems good to me!
> > Ebean.find(Customer.class) > > .where().startsWith("name","A") > > .*filterMany()*.eq("orders.status", > > Order.Status.NEW).gt("orders.orderDate", lastWeek)
> Hmmm ... about the filterMany() api.
> In the above statement it is not clear which relation is filtered. If > you mix filtering *ToMay and Root-Filtering you might get confused.
> At least adding the relation name on filterMany() might be required:
> Ebean.find(Customer.class) > .where().startsWith("name","A") > .*filterMany("orders")*.eq("orders.status", > Order.Status.NEW).gt("orders.orderDate", lastWeek)
> ... or what about that:
> Query<Customer> custQuery = Ebean.find(Customer.class); > custQuery.where().startWith("name", "A");
> Query<Order> custOrderQuery = custQuery.findMany("orders", > Order.class); > custOrderQuery.where().eg("status", Order.Status.NEW).gt("orderDate", > lastWeek);
> But this might be too much work, no?
> Ciao, > Mario
You must
Sign in before you can post messages.
You do not have the permission required to post.
From:
Mario Ivankovits <mario.ivankov... @gmail.com>
Date: Tue, 9 Mar 2010 00:10:56 -0800 (PST)
Local: Tues, Mar 9 2010 3:10 am
Subject: Re: Eager vs Lazy produces different results
> > Query<Customer> custQuery = Ebean.find(Customer.class);
> > custQuery.where().startWith("name", "A");
> > Query<Order> custOrderQuery = custQuery.findMany("orders", > > Order.class); > > custOrderQuery.where().eg("status", Order.Status.NEW).gt("orderDate", > > lastWeek);
Yea, my example was not quite right - probably this makes more sense?
Query<Customer> custQuery = Ebean.find(Customer.class); custQuery.where().startWith("name", "A");
ExpressionList<Order> custOrderQuery = custQuery.findMany("orders", Order.class); custOrderQuery.eg("status", Order.Status.NEW).gt("orderDate", lastWeek);
List<Customer> list = custQuery.findList();
Point is, that I think the findMany() should return some sort of "other" query which one should configure the filter instead of simply "streamlining" it into a normal query. I think that makes it clearer what the result of the criteria will be. For all the eq/gt etc
Next, what if you need to join custQuery and custOrderQuery? Then we would need something like this:
custOrderQuery.eq("xyz", custQuery.getProperty("xyz"));
I would like that syntax, even for the normal "query.join" as then you do not have to take care about the alias stuff.
In fact, in our application I've create a slim query wrapper which simulates that syntax.
Ciao, Mario
You must
Sign in before you can post messages.
You do not have the permission required to post.
From:
Rob Bygrave <robin.bygr... @gmail.com>
Date: Tue, 9 Mar 2010 23:24:04 +1300
Local: Tues, Mar 9 2010 5:24 am
Subject: Re: [ebean] Re: Eager vs Lazy produces different results
findMany() should return some sort of "other" query
<<
Yup - except I think you should drop the word 'query'... and replace with 'filter' or 'expression list'. The "other query" is not a query ... it is just a list of predicates - I'd say 'other filter'.
In that sense I'd rename your "custOrderQuery" variable to "custOrderFilter".
Next, what if you need to join custQuery and custOrderQuery? Then we
would need something like this:
custOrderQuery.eq("xyz", custQuery.getProperty("xyz")); <<
Maybe I misunderstood this... but I don't think this makes sense at the sql level. The joins have different cardinality and are effectively independent.
That is, our fix for the in("validRoles", roleList) ... is to add an extra join to the many that is independent of the 'fetch join' (if there is a fetch join of course).
Having a predicate between the two joins doesn't make sense to me.
On Tue, Mar 9, 2010 at 9:10 PM, Mario Ivankovits <mario.ivankov... @gmail.com
> wrote:
> > > Query<Customer> custQuery = Ebean.find(Customer.class);
> > > custQuery.where().startWith("name", "A");
> > > Query<Order> custOrderQuery = custQuery.findMany("orders", > > > Order.class); > > > custOrderQuery.where().eg("status", Order.Status.NEW).gt("orderDate", > > > lastWeek);
> Yea, my example was not quite right - probably this makes more sense?
> Query<Customer> custQuery = Ebean.find(Customer.class); > custQuery.where().startWith("name", "A");
> ExpressionList<Order> custOrderQuery = custQuery.findMany("orders", > Order.class); > custOrderQuery.eg("status", Order.Status.NEW).gt("orderDate", > lastWeek);
> List<Customer> list = custQuery.findList();
> Point is, that I think the findMany() should return some sort of > "other" query which one should configure the filter instead of simply > "streamlining" it into a normal query. I think that makes it clearer > what the result of the criteria will be. For all the eq/gt etc
> Next, what if you need to join custQuery and custOrderQuery? Then we > would need something like this:
> custOrderQuery.eq("xyz", custQuery.getProperty("xyz"));
> I would like that syntax, even for the normal "query.join" as then you > do not have to take care about the alias stuff.
> In fact, in our application I've create a slim query wrapper which > simulates that syntax.
> Ciao, > Mario
You must
Sign in before you can post messages.
You do not have the permission required to post.
From:
Mario Ivankovits <mario.ivankov... @gmail.com>
Date: Tue, 9 Mar 2010 04:39:45 -0800 (PST)
Local: Tues, Mar 9 2010 7:39 am
Subject: Re: Eager vs Lazy produces different results
>> custOrderQuery.eq("xyz", custQuery.getProperty("xyz"));
> Maybe I misunderstood this... but I don't think this makes sense at the sql > level. The joins have different cardinality and are effectively > independent.
Yep, it is not required to fix this filter thing. I just thought about
it as additional feature ... but yes, nothing we have to address yet.
Ciao, Mario
You must
Sign in before you can post messages.
You do not have the permission required to post.
From:
Rob Bygrave <robin.bygr... @gmail.com>
Date: Wed, 10 Mar 2010 08:47:33 +1300
Local: Tues, Mar 9 2010 2:47 pm
Subject: Re: [ebean] Re: Eager vs Lazy produces different results
ok - cool.
On Wed, Mar 10, 2010 at 1:39 AM, Mario Ivankovits <
mario.ivankov
... @gmail.com> wrote:
> >> custOrderQuery.eq("xyz", custQuery.getProperty("xyz"));
> > Maybe I misunderstood this... but I don't think this makes sense at the > sql > > level. The joins have different cardinality and are effectively > > independent.
> Yep, it is not required to fix this filter thing. I just thought about > it as additional feature ... but yes, nothing we have to address yet.
> Ciao, > Mario
You must
Sign in before you can post messages.
You do not have the permission required to post.
From:
Daryl Stultz <kungfumachin... @gmail.com>
Date: Tue, 9 Mar 2010 13:23:35 -0800 (PST)
Local: Tues, Mar 9 2010 4:23 pm
Subject: Re: Eager vs Lazy produces different results
On Mar 9, 2:24 am, Rob Bygrave <robin.bygr... @gmail.com> wrote:
> > Will it reload the collection as filtered or load the full list?
> I'd suggest as filtered but not sure.
Yeah, that's a tough one. I'm not sure what I'd expect it to do.
/Daryl
You must
Sign in before you can post messages.
You do not have the permission required to post.
From:
Rob Bygrave <robin.bygr... @gmail.com>
Date: Wed, 10 Mar 2010 20:53:39 +1300
Local: Wed, Mar 10 2010 2:53 am
Subject: Re: [ebean] Re: Eager vs Lazy produces different results
Logged the first part of this as bug 239 : http://www.avaje.org/bugdetail-239.html
This is now in head and deployed to:
http://www.avaje.org/archiva/repository/snapshots/org/avaje/ebean/2.5...
I will do some work on the filterMany part aiming for something like Mario's last suggestion and see how that goes.
Query<Customer> rootQuery = ...
ExpressionList<Order> ordersFilter = rootQuery.filterMany("orders",Order.class); ordersFilter.eq("status", Order.Status.NEW).gt("orderDate", lastWeek);
...
On Wed, Mar 10, 2010 at 10:23 AM, Daryl Stultz <kungfumachin... @gmail.com>wrote:
> On Mar 9, 2:24 am, Rob Bygrave <robin.bygr... @gmail.com> wrote: > > > Will it reload the collection as filtered or load the full list?
> > I'd suggest as filtered but not sure.
> Yeah, that's a tough one. I'm not sure what I'd expect it to do.
> /Daryl
You must
Sign in before you can post messages.
You do not have the permission required to post.
From:
Rob Bygrave <robin.bygr... @gmail.com>
Date: Fri, 12 Mar 2010 08:53:18 +1300
Local: Thurs, Mar 11 2010 2:53 pm
Subject: Re: [ebean] Re: Eager vs Lazy produces different results
Logged as http://www.avaje.org/bugdetail-241.html
Fixed in HEAD.
In the end I decided to make filterMany fluent (with the rest of the query) ... which means people have to be a little bit careful that they put their expressions in the right expression list.
It looks pretty comfortable and natural and I felt people using filterMany are probably going to test the behaviour.
List<Customer> list = Ebean.find(Customer.class)
// ... works with fetch/query and lazy joins
// .join("orders", new JoinConfig().lazy()) // .join("orders", new JoinConfig().query()) .join("orders")
// Apply a filter on the root level objects .where().ilike("name","Rob%")
// Apply a filter on the orders that are fetched .filterMany("orders") .eq("status", Order.Status.NEW) .gt("orderDate", lastWeek) .findList();
As a reminder to folks new to this (fairly large) discussion... when their are lots of 'many's (in this case say there are lots of orders for each customer) ... you may want to apply a filter on the 'many's fetch (in this case filter the orders to just get the new orders made since last week).
NB: At this point a refresh on the many property ... will apply/preserve the filter.
// the filter is remembered and applied on refresh Ebean.refreshMany(customer, "orders");
Cheers, Rob.
On Wed, Mar 10, 2010 at 8:53 PM, Rob Bygrave <robin.bygr... @gmail.com>wrote:
> Logged the first part of this as bug 239 :
>
http://www.avaje.org/bugdetail-239.html > This is now in head and deployed to:
> http://www.avaje.org/archiva/repository/snapshots/org/avaje/ebean/2.5...
> I will do some work on the filterMany part aiming for something like > Mario's last suggestion and see how that goes.
> Query<Customer> rootQuery = ...
> ExpressionList<Order> ordersFilter = > rootQuery.filterMany("orders",Order.class); > ordersFilter.eq("status", Order.Status.NEW).gt("orderDate", lastWeek);
> ...
> On Wed, Mar 10, 2010 at 10:23 AM, Daryl Stultz <kungfumachin... @gmail.com>wrote:
>> On Mar 9, 2:24 am, Rob Bygrave <robin.bygr... @gmail.com> wrote: >> > > Will it reload the collection as filtered or load the full list?
>> > I'd suggest as filtered but not sure.
>> Yeah, that's a tough one. I'm not sure what I'd expect it to do.
>> /Daryl
You must
Sign in before you can post messages.
You do not have the permission required to post.
From:
Daryl Stultz <kungfumachin... @gmail.com>
Date: Thu, 11 Mar 2010 18:01:02 -0800 (PST)
Local: Thurs, Mar 11 2010 9:01 pm
Subject: Re: Eager vs Lazy produces different results
On Mar 11, 2:53 pm, Rob Bygrave <robin.bygr... @gmail.com> wrote:
Hi Rob, thanks for working on this. I've updated and rebuilt from source.
> NB: At this point a refresh on the many property ... will apply/preserve the
> filter.
> // the filter is remembered and applied on refresh > Ebean.refreshMany(customer, "orders");
I don't see this behavior. Maybe I'm not understanding things. Here's
my test. I have one user with 2 validRoles, role1 and role2.
List<Integer> roleIds = new ArrayList<Integer>(); roleIds.add(role1.getId()); List<User> userResults = Ebean.find(User.class).join("validRoles").where().in("validRoles.id", roleIds).findList(); assertEquals(1, userResults.size()); User resultUser = userResults.get(0); assertEquals(user, resultUser); assertEquals(2, resultUser.getValidRoles().size()); // used to return filtered Ebean.refreshMany(resultUser, "validRoles"); assertEquals(2, resultUser.getValidRoles().size());
userResults = Ebean.find(User.class).join("validRoles") .where().in("validRoles.id", roleIds) // roleIds contains only role1 id .filterMany("validRoles").eq("name", "role2") .findList(); assertEquals(1, userResults.size()); resultUser = userResults.get(0); assertEquals(user, resultUser); assertEquals(1, resultUser.getValidRoles().size()); assertEquals(role2, resultUser.getValidRoles().get(0)); Ebean.refreshMany(resultUser, "validRoles"); assertEquals(1, resultUser.getValidRoles().size()); // expected 1 but was 2
It fails on the last line. So I'm restricting user by role1 and filtering validRoles by role2. It works until the refresh.
/Daryl
You must
Sign in before you can post messages.
You do not have the permission required to post.
From:
Rob Bygrave <robin.bygr... @gmail.com>
Date: Sun, 14 Mar 2010 17:10:13 +1300
Local: Sat, Mar 13 2010 11:10 pm
Subject: Re: [ebean] Re: Eager vs Lazy produces different results
Yes, I reproduced this and fixed it in HEAD.
Thanks, Rob.
On Fri, Mar 12, 2010 at 3:01 PM, Daryl Stultz <kungfumachin... @gmail.com>wrote:
> On Mar 11, 2:53 pm, Rob Bygrave <robin.bygr... @gmail.com> wrote:
> Hi Rob, thanks for working on this. I've updated and rebuilt from > source.
> > NB: At this point a refresh on the many property ... will apply/preserve > the > > filter.
> > // the filter is remembered and applied on refresh > > Ebean.refreshMany(customer, "orders");
> I don't see this behavior. Maybe I'm not understanding things. Here's > my test. I have one user with 2 validRoles, role1 and role2.
> List<Integer> roleIds = new ArrayList<Integer>(); > roleIds.add(role1.getId()); > List<User> userResults = > Ebean.find(User.class).join("validRoles").where().in("validRoles.id", > roleIds).findList(); > assertEquals(1, userResults.size()); > User resultUser = userResults.get(0); > assertEquals(user, resultUser); > assertEquals(2, resultUser.getValidRoles().size()); // used to return > filtered > Ebean.refreshMany(resultUser, "validRoles"); > assertEquals(2, resultUser.getValidRoles().size());
> userResults = Ebean.find(User.class).join("validRoles") > .where().in("validRoles.id", roleIds) // roleIds contains only role1 > id > .filterMany("validRoles").eq("name", "role2") > .findList(); > assertEquals(1, userResults.size()); > resultUser = userResults.get(0); > assertEquals(user, resultUser); > assertEquals(1, resultUser.getValidRoles().size()); > assertEquals(role2, resultUser.getValidRoles().get(0)); > Ebean.refreshMany(resultUser, "validRoles"); > assertEquals(1, resultUser.getValidRoles().size()); // expected 1 but > was 2
> It fails on the last line. So I'm restricting user by role1 and > filtering validRoles by role2. It works until the refresh.
> /Daryl
You must
Sign in before you can post messages.
You do not have the permission required to post.
From:
Daryl Stultz <kungfumachin... @gmail.com>
Date: Mon, 15 Mar 2010 06:05:49 -0700 (PDT)
Local: Mon, Mar 15 2010 9:05 am
Subject: Re: Eager vs Lazy produces different results
On Mar 14, 12:10 am, Rob Bygrave <robin.bygr... @gmail.com> wrote:
> Yes, I reproduced this and fixed it in HEAD.
Confirmed.
/Daryl
You must
Sign in before you can post messages.
You do not have the permission required to post.