I’m in favor of #2. I implemented a solution similar to this a long time ago for an app that had a few expensive relationships. I wouldn’t recommend my implementation (I wrote it about 12 years ago at this point), but the approach worked well.
Robert > On Oct 9, 2017, at 6:54 AM, Andrus Adamchik <and...@objectstyle.org> wrote: > > Some to-many relationships have reasonably small size. Others do not. Tens, > hundreds, even thousands of objects are all "reasonable". Millions are not. > Often relationships from "lookup" / configuration tables are in the later > category (e.g. "user_type" -> "user", where "user" has millions of records). > My "normal" approach to such relationships is to avoid them all together. I > map them on Db* side, but skip them on the Obj* side. Cayenne supports > one-way relationships and it works pretty well. The assumption is that there > are no realistic scenarios for traversing such relationships in memory all at > once. If I ever need all users for a given type, I'd write a query and run it > as an iterator, or add an extra qualifier to work with a smaller subset of > users. > > Today I ran into an issue where I could not easily bypass these relationships > (and as expected all these objects are faulted into memory). The scenario is > "Deny" delete rule (e.g. when deleting a user_type, check that there are no > users for this type, and throw DeleteDenyException otherwise). If I don't map > "user_type" -> "user" relationship, I can't setup the "Deny" rule. The delete > is still denied due to the DB-side FK constraint, but I can't build a > user-friendly error message. > > I see a few ways to solve this. Anyways: > > 1. We can move delete rules from ObjRelationship to DbRelationship level. And > then implement the delete rule to check in-memory relationship first, and if > not faulted, run some form of EXISTS query that checks related records > presence without faulting them in memory. That's a model change. And it > sidesteps dealing with huge relationships in general, focusing on this single > case. Feels like one of those minor edge cases that will require a massive > refactoring effort to fix :) > > 2. We can treat these huge ObjRelationships as a special type of > relationships (marked as such in the Modeler), and apply special strategies > to them. E.g. pagination on faulting, List.isEmpty() and List.size() resolved > without faulting (thus allowing to deal with Deny rule). > > 3. And the simplest of them - don't map such relationships, don't map delete > rules, and handle "Deny" in a 'validateForDelete'. > > Both 1&2 have benefits and downsides. I am still undecided how to better > handle it (and whether I should bother at all, and instead just use #3). In > any event I figured I'd mention it here. Perhaps somebody has some thoughts > on it. > > Cheers, > Andrus