Thanks to you and Christian, it has been very helpful. I'll wait the answers on 
Ebeans out and decide then :-)

A few thoughts wrapping stuff up:

> There is no (clean) way to have a lazy, non-mandatory toOne relationship.

Ah. An interesting snag that I haven't hit yet.
Seems to be a quite rare case though. Making a to-one association eager usually 
isn't a performance problem. Unless you're in a situation where you need 
per-column laziness, too, but at least in my case, that's not a real issue. 
(The database server keeps 70% of the total database in RAM anyway...)

> one of the devs basically said that he thought lazy fetching was a bad idea;
> an application should know at the beginning of the request what data it
> needs and fetch it all in one swoop.

Well, he's ignoring important use cases.
Besides, I don't see the point; if you have a way to reattach objects, you have 
thrown transactional integrity out of the window anyway.

What's needed is a way to verify integrity on writeback time. I.e. 
declaratively identify all the dependencies between data, and on commit, let 
the framework check that modified fields don't depend on fields that were 
concurrently modified.

> Hibernate does have lazy loading now, but I still find it... finicky.
> It's way too easy to hit LazyInitializationException.

In my eyes, it's combining the disadvantages of strict discipline with the 
disadvantages of missing transactional integrity.

Hibernate doesn't seem to be very clear about concepts in general. The whole 
codebase has an "additive" feel - like lots of interfaces heaped on top of each 
other, and each new feature written anew

> 4) runtime metadata.  You can get the metadata (mapping info) for
> entities in hibernate and in cayenne, but it's messed up in hibernate. :)

Heh. Been there, done that.
It *is* possible, and I got all the info that I needed. The awkwardness is 
because Hibernate offers the info at the database layer, and you need to know 
how that translates back up to the POJO level. Once you got that, it's all 
pretty straightforward though.

One caveat: I'd have to reengineer things a bit if I ever get into the 
situation where multiple database fields map to a single Java property. It 
would be doable but I'd have to make a whole lot of my own code understand 
multiple-field attributes, so I have left that as an exercise to the reader :D

> 1) I do (kind of) like the annotation-based approach that is now
> available in hibernate.

Yes, those annotations are cool.
Unfortunately, they didn't cover everything that the .hbm.xml mechanism covers, 
so I went back to .hbm.xml (with gritted teeth).
I understand that annotations are moving along, so this may be different today 
than it was 18 months ago.

> Not enough to abandon Cayenne + Cayenne Modeler, but if you like having
> all of the modeling info directly in your source (some do, some don't),
> or you like building your object and annotating on the fly, then this is nice.

I do.
But... well... it didn't work very well in Hibernate anyway.
And if it's the database that leads, you're tied to Hibernate's reverse 
engineering process, which distributes a lot of relevant semantic information 
into a single monolithic configuration file. Which plain sucks if you want the 
table-specific configuration in one place.

I guess Cayenne can't do worse than that :-)

> 2) Hibernate's implementation of inheritance is (probably) more complete
> than Cayenne's

An interesting point, but not for my current project. We're doing oldschool DB 
design here, and inheritance doesn't really exist (except in the form of joined 
tables).

> Cayenne also supports vertical/"joined table inheritance", where you have
> one table for the superclass, and then a table for each subclass.

That's good enough for us.
After all, the database must be usable for ad-hoc SQL queries; fancy 
subclassing schemes don't work too well with that.

>  Cayenne currently doesn't support "horizontal" inheritance (no table for the
> superclass; one table for each concrete subclass); hibernate does.  If you
> need that, you'll have to stick with hibernate (my condolences :).

You can always code around that. Use static functions for the common 
functionality across the tables.
You don't get the encapsulation, but you do get the refactoring. (If people do 
ad-hoc queries, you're in unencapsulated land anyway, so you had that loss 
already.)

> 2) Starting with a new technology is always a risk, but generally, I think
> your risk is reasonably low with Cayenne. If you're beating your head against
> the wall with Hibernate,

I am, else I wouldn't be looking into alternatives. Switching horses in 
mid-races is the worst thing you can do, unless you are already banging your 
head against a stone wall.

> 4) ... maybe this is just me, but, I /usually/ try to avoid storing data
> that can be calculated.  Sometimes it's justified, if the calculation is 
> expensive,

Heh. I'm 100% with you on that.

The issue is: people are scrolling through lists of orders. Many orders have a 
five-digit number of positions. I can't have the DB calculate that on the fly - 
not if they're doing a quick review over the last month's worth or orders, 
which would mean hundred thousands or millions of rows that go into the sums to 
be shown.

The only way out that I really see is Oracle's "materialized views". But we 
want to be portable, at least in principle, and materialized views aren't in 
any standard yet.

> With the right query cache strategy, it should be performant.

Well, the data changes rarely if ever. (I wouldn't be considering storing a sum 
field in the Order table otherwise.)
I still am worried about performance.

Plus there's the other problem: People want to see the sums in ad-hoc SQL, so 
I'm pretty much stuck with storing the sum in a table. (I could place it in a 
view, of course. Potentially making it slow, plus query users will have to 
remember to use the view for SELECT and the table for UPDATE.)

> 5) They aren't nested transactions; they are nested contexts.

Sorry, I was being sloppy with wording. I was thinking entirely from the 
perspective of code that does data modifications, in which case the only 
relevant property of DB transations is rollback, which is shared by contexts 
(as far as I understand contexts).

My guess is that contexts share the rollback semantics of nested transactions. 
They certainly don't share the commit semantics, they'd fail with that on 
Persistence alone.

Regards,
Jo

Reply via email to