We have a double 1-N setup with cascade delete: A -> B -> C.
If we delete A then all referred B's and by those referred C's are deleted. Eclipselink does this by first selecting all the referred B's and then selecting all the referred C's and then deleting them. This naturally is very inefficient from a database perspective, but I understand that this is required to make sure the cache is correct.
The only way to do this more efficiently is to use native sql and clear both level caches?
If you use @PrivateOwned instead of cascade EclipseLink should optimize the deletion to avoid reading in the related objects. It will still read in B to delete the C's, but should not need to read C, unless C is using optimistic locking or has its own dependencies.
You could set the cascade on the constraint in the database instead of in JPA. This would mean that A would be removed from the cache, but not B or C. This might be ok, B and C should eventually garbage collect from the cache. The only way you could get B or C would be by a primary key query, if your app would never do this, then may be fine just leaving the cache as is. Otherwise you could invalidate the C and B caches.