views:

2012

answers:

11

Is there a viable alternative to Hibernate? Preferably something that doesn't base itself on JPA.

Our problem is that we are building a complex (as in, many objects refer to each other) stateful RIA system. It seems as Hibernate is designed to be used mainly on one-off applications - JSF and the like.

The problem is mainly that of lazy loading. Since there can be several HTTP requests between the initialization and actually loading lazy collections, a session per transaction is out of the question. A long-lived session (one per application) doesn't work well either, because once a transaction hits a snag and throws an exception, the whole session is invalidated, thus the lazy loaded objects break. Then there's all kinds of stuff that just don't work for us (like implicit data persisting of data from outside an initialized transaction).

My poor explanations aside, the bottom line is that Hibernate does magic we don't like. It seems like TopLink isn't any better, it also being written on top of EJB.

So, a stateless persistence layer (or even bright-enough object-oriented database abstraction layer) is what we would need the most.

Any thoughts, or am I asking for something that doesn't exist?

Edit: I'm sorry for my ambiguous terminology, and thank you all for your corrections and insightful answers. Those who corrected me, you are all correct, I meant JPA, not EJB.

+5  A: 

If you're after another JPA provider (Hibernate is one of these) then take a look at EclipseLink. It's far more fully-featured than the JPA 1.0 reference implementation of TopLink Essentials. In fact, EclipseLink will be the JPA 2.0 reference implementation shipped with Glassfish V3 Final.

JPA is good because you can use it both inside and outside a container. I've written Swing clients that use JPA to good effect. It doesn't have the same stigma and XML baggage that EJB 2.0/2.1 came with.

If you're after an even lighter weight solution then look no further than ibatis, which I consider to be my persistence technology of choice for the Java platform. It's lightweight, relies on SQL (it's amazing how much time ORM users spend trying to make their ORM produce good SQL) and does 90-95% of what JPA does (including lazy loading of related entities if you want).

Just to correct a couple of points:

  • JPA is the peristence layer of EJB, not built on EJB;
  • Any decent JPA provider has a whole lot of caching going on and it can be hard to figure it all out (this would be a good example of "Why is Simplicity So Complex?"). Unless you're doing something you haven't indicatd, exceptions shouldn't be an issue for your managed objects. Runtime exceptions typically rollback transactions (if you use Spring's transaction management and who doesn't do that?). The provider will maintain cached copies of loaded or persisted objects. This can be problematic if you want to update outside of the entity manager (requiring an explicit cache flush or use of EntityManager.refresh()).
cletus
Thanks, I'll take a look at ibatis
Henrik Paul
+2  A: 

I've looked at SimpleORM last year, and was very impressed by its lightweight no-magic design. Now there seems to be a version 3, but I don't have any experience with that one.

David Schmitt
A: 

Neither Hibernate nor Toplink (EclipseLink) is based on EJB, they are both POJO persistancy frameworks (ORM).

I agree with the previous answer: iBatis is a good alternative to ORM frameworks: full control over sql, with a good caching mechanism.

Andrej
A: 

One other option is Torque, I am not saying it is better than any of the options mentioned above but just that it is another option to look at. It is getting quite old now but may fit some of your requirements.

Torque

Shawn
+2  A: 

I think you should have a look at apache cayenne which is a very good alternative to "big" frameworks. With its decent modeler, the learning curve is shorten by a good documentation.

frederic.jecker
+5  A: 

As mentioned, JPA <> EJB, they're not even related. EJB 3 happens to leverage JPA, but that's about it. We have a bunch of stuff using JPA that doesn't even come close to running EJB.

Your problem is not the technology, it's your design.

Or, I should say, your design is not an easy fit on pretty much ANY modern framework.

Specifically, you're trying to keep transactions alive over several HTTP requests.

Naturally, most every common idiom is that each request is in itself one or more transactions, rather than each request being a portion of a larger transaction.

There is also obvious confusion when you used the term "stateless" and "transaction" in the same discussion, as transactions are inherently stateful.

Your big issue is simply managing your transactions manually.

If you transaction is occurring over several HTTP requests, AND those HTTP requests happen to be running "very quicky", right after one another, then you shouldn't really be having any real problem, save that you WILL have to ensure that your HTTP requests are using the same DB connection in order to leverage the Databases transaction facility.

That is, in simple terms, you get a connection to the DB, stuff it in the session, and make sure that for the duration of the transaction, all of your HTTP requests go through not only that same session, but in such a way that the actual Connection is still valid. Specifically, I don't believe there is an off the shelf JDBC connection that will actually survive failover or load balancing from one machine to another.

So, simply, if you want to use DB transactions, you need to ensure that your using the same DB Connection.

Now, if your long running transaction has "user interactions" within it, i.e. you start the DB transaction and wait for the user to "do something", then, quite simply, that design is all wrong. You DO NOT want to do that, as long lived transactions, especially in interactive environments, are just simply Bad. Like "Crossing The Streams" Bad. Don't do it. Batch transactions are different, but interactive long lived transactions are Bad.

You want to keep your interactive transactions as short lived as practical.

Now, if you can NOT ensure you will be able to use the same DB connection for your transaction, then, congratulations, you get to implement your own transactions. That means you get to design your system and data flows as if you have no transactional capability on the back end.

That essentially means that you will need to come up with your own mechanism to "commit" your data.

A good way to do this would be where you build up your data incrementally into a single "transaction" document, then feed that document to a "save" routine that does much of the real work. Like, you could store a row in the database, and flag it as "unsaved". You do that with all of your rows, and finally call a routine that runs through all of the data you just stored, and marks it all as "saved" in a single transaction mini-batch process.

Meanwhile, all of your other SQL "ignores" data that is not "saved". Throw in some time stamps and have a reaper process scavenging (if you really want to bother -- it may well be actually cheaper to just leave dead rows in the DB, depends on volume), these dead "unsaved" rows, as these are "uncomitted" transactions.

It's not as bad as it sounds. If you truly want a stateless environment, which is what it sounds like to me, then you'll need to do something like this.

Mind, in all of this the persistence tech really has nothing to do with it. The problem is how you use your transactions, rather than the tech so much.

Will Hartung
Thanks for your comments. Sorry for being unclear with my terminology, but you have hit our problem in the head. That's actually what our team is doing at the moment. I just was hoping there would've been an easier way...
Henrik Paul
A: 

BEA Kodo (formerlly Solarmetric Kodo) is another alternative. It supports JPA, JDO, and EJ3. It is highly configurable and can support agressive pre-fetching, detaching/attaching of objects, etc.

Though, from what you've described, Toplink should be able to handle your problems. Mostly, it sounds like you need to be able to attach/detach objects from the persistence layer as requests start and end.

James Schek
A: 

When I was myself looking for a replacement to Hibernate I stumbled upon DataNucleus Access Platform, which is an Apache2-licensed ORM. It isn't just ORM as it provides persistence and retrieval of data also in other datasources than RDBMS, like LDAP, DB4O and XML. I don't have any usage experience, but it looks interesting.

Kaitsu
A: 

Consider breaking your paradigm completely with something like tox. If you need Java classes you could load the XML result into JDOM.

dacracot
+2  A: 

I did a short compilation of ORM Solutions for Java here:

http://www.jonasbandi.net/wiki/index.php/ORM_Solutions_for_Java

This list is by no means complete, but it contains the ORM-frameworks I would consider when starting a new project today.

jbandi
+2  A: 

Ebean ORM (http://www.avaje.org)

It is a simpler more intuitive ORM to use.

  • Uses JPA Annotations for Mapping (@Entity, @OneToMany etc)
  • Sessionless API - No Hibernate Session or JPA Entity Manager
  • Lazy loading just works
  • Partial Object support for greater performance
  • Automatic Query tuning via "Autofetch"
  • Spring Integration
  • Large Query Support
  • Great support for Batch processing
  • Background fetching
  • DDL Generation
  • You can use raw SQL if you like (as good as Ibatis)
  • LGPL licence

  • Rob.

Rob