cayenne-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Andrus Adamchik <>
Subject huge to-many relationships
Date Mon, 09 Oct 2017 11:54:48 GMT
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.

View raw message