Hi Samuel,

Yeah, Expressions (the things actually generated by the Properties) can be used 
for both querying the DB and for in-memory evaluation, i.e. what you call 
"object queries”. I haven’t looked much into how much you can do “in-memory” 
with the more complex Expressions though, have to do some experimentation on 
that.

I’d like to say “yes” regarding using some of that Property magic on generic 
objects/methods rather than Persistent object attributes, I certainly have in 
the past. But Cayenne is focused on using this for Persistent objects and their 
modeled attributes so there might be caveats I don’t know of currently. I have 
replaced most of the code where I used Cayenne to perform actions on generic 
objects/methods with Streams, but I know what you mean — ERXKey/Property is 
certainly nicer in some ways, especially when it comes to working with nested 
objects (long keypaths).

Feel free to hit me up here or in #cayenne on Slack if you decide to check out 
Cayenne and need some rubber ducking. I incidentally made a video last night 
for another WO guy on creating a simple WO/Cayenne project from scratch. It 
auto-generates an in-memory h2 database at application startup from the model, 
meaning you can play around with adding things to the model and try out 
features along the way.

Video:
https://www.youtube.com/watch?v=Ahu3Qnki1-w

Project: 
https://github.com/hugithordarson/cay

Cheers,
- hugi

PS: The example query in the previous message was kind of nonsensical (sum on 
receipt total? wat?) and I even pasted in the wrong SQL (generated by a 
previous version of the example query). Pardon that, I’ll probably write a 
short article and then include some actual, correct examples :)



> On 3 Feb 2025, at 13:56, Samuel Pelletier <sam...@samkar.com> wrote:
> 
> Hi Hugi,
> 
> So those Properties can build objects queries AND more custom queries like 
> ERXQuery, seems very cool.
> 
> Can you create Properties for EO methods ? I have many of them for things 
> like "return a previously set value or compute a default one"...
> 
> I want to play with Cayenne but have not found the real good yet... Porting a 
> large application seems a bit too big to experiment a new frameworks but I 
> have a personal project that seems a very good fit.
> 
> Regards,
> 
> Samuel
> 
> 
>> Le 3 févr. 2025 à 08:12, Hugi Thordarson via Webobjects-dev 
>> <webobjects-dev@lists.apple.com> a écrit :
>> 
>> Hi Samuel,
>> 
>> Yes, we have a very nice querying API/syntax similar to ERXKey in Cayenne 
>> (although they’re called “Properties” in the Cayenne world).
>> 
>> For example, selecting all my receipts, ordering them by date and 
>> prefetching their entries:
>> 
>> ====
>> ObjectSelect
>> .query( Receipt.class )
>> .where( Receipt.USER.dot( User.NAME ).eq( “Hugi Þórðarson” ) )
>> .orderBy( Receipt.SHOP ).dot( Shop.NAME ).desc() )
>> .prefetch( Receipt.ENTRIES.joint();
>> .select( objectContext );
>> ====
>> 
>> They’ve also evolved quite a bit in the last years along with Cayenne’s 
>> SQL/querying abilities and now include fun stuff like SQL subqueries, 
>> aggregates, functions and features like EXISTS and HAVING. So for a more 
>> complex example, selecting a [Receipt]’s date/total, the related [Shop]’s 
>> name, the number of it’s related [Entry] records, with a creation_date in 
>> year 2023, where they have more than five entries, a higher total than 1.000 
>> and have a related OcrResult object (nonsensical query, but yeah… it’s a 
>> demo):
>> 
>> ====
>> ObjectSelect
>> .query( Receipt.class )
>> .columns(
>> Receipt.DATE_ONLY,
>> Receipt.TOTAL_AS_WRITTEN_ON_RECEIPT,
>> Receipt.SHOP.dot( Shop.NAME ),
>> Receipt.ENTRIES.count()
>> )
>> .where(
>> Receipt.USER.dot( User.NAME ).in( "Hugi Þórðarson", "Ósk Gunnlaugsdóttir" )
>> .andExp( Receipt.CREATION_DATE.year().eq( 2023 ) )
>> .andExp( Receipt.OCR_RESULTS.exists() )
>> )
>> .having(
>> Receipt.ENTRIES.count().gt( 5l )
>> .andExp( Receipt.TOTAL_AS_WRITTEN_ON_RECEIPT.sum().gt( BigDecimal.valueOf( 
>> 1000 ) ) )
>> )
>> .orderBy(
>> Receipt.ENTRIES.count().desc()
>> )
>> .select( oc );
>> ====
>> 
>> … generating the following SQL:
>> 
>> ====
>> SELECT "t0"."date_only", "t1"."name", COUNT( "t2"."id" ), 
>> "t0"."total_as_written_on_receipt" FROM "fd_receipt" "t0" JOIN "fd_shop" 
>> "t1" ON "t0"."shop_id" = "t1"."id" JOIN "fd_entry" "t2" ON "t0"."id" = 
>> "t2"."receipt_id" JOIN "fd_user" "t3" ON "t0"."user_id" = "t3"."id" WHERE ( 
>> "t3"."name" = ? ) AND ( EXTRACT(YEAR FROM "t0"."creation_date") = ? ) AND 
>> EXISTS (SELECT "t4"."id" FROM "fd_ocr_result" "t4" WHERE "t4"."receipt_id" = 
>> "t0"."id") GROUP BY "t0"."date_only", "t1"."name", 
>> "t0"."total_as_written_on_receipt" HAVING ( ( COUNT( "t2"."id" ) > ? ) AND ( 
>> SUM( "t0"."total_as_written_on_receipt" ) > ? ) ) ORDER BY COUNT( "t2"."id" 
>> ) DESC [bind: 1->name:'Hugi Þórðarson', 2:2023, 3:5, 4:1000]
>> ====
>> 
>> This showcases just a part of the features, and works so well it feels 
>> almost magical at times. I could also have specified Receipt.SELF as a 
>> “column” instead of fetching specific values of the Receipt entity, meaning 
>> I get the entire Receipt object (with all it's associated ORM features) 
>> along with it’s aggregate values. I use this quite a lot (didn’t do that in 
>> the example since it makes the resulting SQL longer, since there’s a lot of 
>> columns involved).
>> 
>> And yes, you can use Properties to perform in-memory operations like 
>> filtering and sorting.
>> 
>> Receipt.CREATION_DATE.desc().orderedList( receipt );
>> Receipt.USER.dot( User.NAME ).eq( “Hugi” ).filterObjects ( receipts );
>> 
>> Cheers,
>> - hugi
>> 
>> 
>> 
>>> On 3 Feb 2025, at 12:18, Samuel Pelletier via Webobjects-dev 
>>> <webobjects-dev@lists.apple.com> wrote:
>>> 
>>> HI,
>>> 
>>> Those NS collections where essentials in the first java WO mainly because 
>>> at that time Java did not had real collections classes (they appeared in 
>>> Java 1.8), and the name was probably kept to help porting. I did not switch 
>>> to java WO at that time and maintained some objective-C apps for a long 
>>> time!
>>> 
>>> I mostly use the NS versions because I'm still on EOF and uses ERXKey for 
>>> sort orderings, qualifier building and aggregate computation to have type 
>>> checking:
>>> 
>>> - EOQualifier qualifier = 
>>> Evenement.DATE.greaterThanOrEqualTo(dateDebut()).and(Evenement.DATE.lessThanOrEqualTo(dateFin()));
>>> - ERXKey.sum(ContratRetenue.NB_HEURES).valueInObject(retenues);
>>> - NSArray<Etudiant> etudiants = 
>>> Groupe.ETUDIANTS_ACTIFS.atFlatten().arrayValueInObject(evenement.groupes());
>>> -          sortOrderings = Evenement.DATE.asc()
>>>       .then(Evenement.ORDRE_AFF_MOIS_SALLE.asc())
>>>       
>>> .then(Evenement.GROUPE_PRINCIPAL.dot(Groupe.SEMESTRE_DEBUT.dot(Semestre.DATE_DEBUT)).desc()
>>>       .then(Evenement.HEURE_DEBUT.asc()));
>>> 
>>> I still think those are more readable than creating lambda, probably mostly 
>>> explained because I'm use to the syntax.
>>> 
>>> Is there something like ERXKey when using Cayenne ?
>>> 
>>> Regards,
>>> 
>>> Samuel
>>> 
>>> 
>>>> Le 2 févr. 2025 à 07:21, Amedeo Mantica via Webobjects-dev 
>>>> <webobjects-dev@lists.apple.com> a écrit :
>>>> 
>>>> Iirc the NS collections were there due to simplifying porting of apps from 
>>>> objc to Java. I don’t think there is any big difference in performance 
>>>> 
>>>> Sent from my iPhone
>>>> 
>>>>> On 2 Feb 2025, at 12:18, Jérémy DE ROYER via Webobjects-dev 
>>>>> <webobjects-dev@lists.apple.com> wrote:
>>>>> 
>>>>>  Hi all, 
>>>>> 
>>>>> Even if I still use EOF (due to inheritance limitations of Cayenne), I 
>>>>> followed Hugi’s precepts :
>>>>> - «  use 100% java native whenever possible »
>>>>> 
>>>>> One other advantage when working in a team… is that 100% java is widely 
>>>>> documented and exampled... and it's more attractive to newbees.
>>>>> 
>>>>> Sorry if I don’t « really » answer the question 😄
>>>>> 
>>>>> Jérémy
>>>>> 
>>>>>> Le 2 févr. 2025 à 11:13, Hugi Thordarson via Webobjects-dev 
>>>>>> <webobjects-dev@lists.apple.com> a écrit :
>>>>>> 
>>>>>> When I made the switch to Java collections I did do some benchmarking. 
>>>>>> Haven’t got the code anymore (this was a decade ago) but at that time, 
>>>>>> the Java collection classes were faster, but the operations were really 
>>>>>> so fast in both cases that the differences were negligible — at that 
>>>>>> time.
>>>>>> 
>>>>>> Since then, a decade of improvements has happened in the Java 
>>>>>> collections so I think we can guess where you’ll find performance 
>>>>>> improvements — and will keep getting performance improvements. On one 
>>>>>> hand you have old classes written in an old version of Java, on the 
>>>>>> other hand you have actively maintained open source classes used by 
>>>>>> millions of programmers and maintained by the performance-obsessed 
>>>>>> authors of Java and the JDK itself.
>>>>>> 
>>>>>> And now for the opinion piece:
>>>>>> Unless you’re writing extremely performance-sensitive code — even if the 
>>>>>> foundation collections were faster I think it makes sense to use Java 
>>>>>> collections and write to the standard Java collection APIs where you 
>>>>>> don’t *need* foundation collections, because If you’re using foundation 
>>>>>> specific APIs, your code is really already obsolete at the time of 
>>>>>> writing. I never regretted the switch and have hardly seen an NS* 
>>>>>> collection class in my code in years, except where explicitly required 
>>>>>> as a parameter for passing into WO APIs. (that story may be a little 
>>>>>> different if you’re using EOF which uses the NS collections everywhere, 
>>>>>> so this may not apply in that case).
>>>>>> 
>>>>>> The Java collection classes do have their warts, the most obvious one to 
>>>>>> us coming from the NS* world being the non-API-differentiation between 
>>>>>> mutable and immutable collections (weird design oversight) but that 
>>>>>> hasn't plagued me, really. It’s just something you’re aware of and don’t 
>>>>>> really hit often.
>>>>>> 
>>>>>> Another one for us WO users is that you can’t use KVC operators on Java 
>>>>>> collections (someArray.@sortAsc, .@sum etc). When I made the switch I 
>>>>>> always thought I’d miss these hugely and planned to write operator 
>>>>>> support into ERXComponent’s valueForKeyPath(), but never got around to 
>>>>>> it since I really didn’t miss the operators, preferring to keep my logic 
>>>>>> in Java rather than templates (compile time errors and refactoring 
>>>>>> support are awesome things).
>>>>>> 
>>>>>> Probably just saying things you know — but I thought it might have some 
>>>>>> value hearing from someone that moved to Java collections and doesn’t 
>>>>>> regret it.
>>>>>> 
>>>>>> Cheers,
>>>>>> - hugi
>>>>>> 
>>>>>> 
>>>>>>> On 2 Feb 2025, at 00:29, ocs--- via Webobjects-dev 
>>>>>>> <webobjects-dev@lists.apple.com> wrote:
>>>>>>> 
>>>>>>> Hi there,
>>>>>>> 
>>>>>>> did ever anybody tried some benchmarks to find whether it is better to 
>>>>>>> use WO collections (NSArray, NSDictionary...) as widely as possible (ie 
>>>>>>> essentially anywhere, unless one really needs to store nulls or can't 
>>>>>>> do without ConcurrentHashMap or so), or whether it's better to use 
>>>>>>> standard collections (List, HashMap...) wherever they happen to work 
>>>>>>> properly (which is surprisingly often, but not anywhere)?
>>>>>>> 
>>>>>>> Are they roughly comparable, or are one or the others considerably 
>>>>>>> better?
>>>>>>> 
>>>>>>> Thanks!
>>>>>>> OC
>>>>>>> 
>>>>>>> _______________________________________________
>>>>>>> Do not post admin requests to the list. They will be ignored.
>>>>>>> Webobjects-dev mailing list      (Webobjects-dev@lists.apple.com)
>>>>>>> Help/Unsubscribe/Update your Subscription:
>>>>>>> https://lists.apple.com/mailman/options/webobjects-dev/hugi%40karlmenn.is
>>>>>>> 
>>>>>>> This email sent to h...@karlmenn.is
>>>>>> 
>>>>>> _______________________________________________
>>>>>> Do not post admin requests to the list. They will be ignored.
>>>>>> Webobjects-dev mailing list      (Webobjects-dev@lists.apple.com)
>>>>>> Help/Unsubscribe/Update your Subscription:
>>>>>> https://lists.apple.com/mailman/options/webobjects-dev/jeremy.deroyer%40ingencys.net
>>>>>> 
>>>>>> This email sent to jeremy.dero...@ingencys.net
>>>>> 
>>>>> _______________________________________________
>>>>> Do not post admin requests to the list. They will be ignored.
>>>>> Webobjects-dev mailing list      (Webobjects-dev@lists.apple.com)
>>>>> Help/Unsubscribe/Update your Subscription:
>>>>> https://lists.apple.com/mailman/options/webobjects-dev/amedeomantica%40me.com
>>>>> 
>>>>> This email sent to amedeomant...@me.com
>>>> _______________________________________________
>>>> Do not post admin requests to the list. They will be ignored.
>>>> Webobjects-dev mailing list      (Webobjects-dev@lists.apple.com)
>>>> Help/Unsubscribe/Update your Subscription:
>>>> https://lists.apple.com/mailman/options/webobjects-dev/samuel%40samkar.com
>>>> 
>>>> This email sent to sam...@samkar.com
>>> 
>>> _______________________________________________
>>> Do not post admin requests to the list. They will be ignored.
>>> Webobjects-dev mailing list      (Webobjects-dev@lists.apple.com)
>>> Help/Unsubscribe/Update your Subscription:
>>> https://lists.apple.com/mailman/options/webobjects-dev/hugi%40karlmenn.is
>>> 
>>> This email sent to h...@karlmenn.is
>> 
>> _______________________________________________
>> Do not post admin requests to the list. They will be ignored.
>> Webobjects-dev mailing list      (Webobjects-dev@lists.apple.com)
>> Help/Unsubscribe/Update your Subscription:
>> https://lists.apple.com/mailman/options/webobjects-dev/samuel%40samkar.com
>> 
>> This email sent to sam...@samkar.com
> 

 _______________________________________________
Do not post admin requests to the list. They will be ignored.
Webobjects-dev mailing list      (Webobjects-dev@lists.apple.com)
Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/webobjects-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Reply via email to