Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

An alternative to Hibernate or TopLink? [closed]

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.

like image 343
Henrik Paul Avatar asked Jan 05 '09 13:01

Henrik Paul


6 Answers

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()).
like image 97
cletus Avatar answered Nov 09 '22 15:11

cletus


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.

like image 26
Will Hartung Avatar answered Nov 09 '22 16:11

Will Hartung


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.

like image 44
Binary9 Avatar answered Nov 09 '22 16:11

Binary9


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.

like image 23
David Schmitt Avatar answered Nov 09 '22 16:11

David Schmitt


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.

like image 2
Rob Bygrave Avatar answered Nov 09 '22 15:11

Rob Bygrave


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.

like image 1
James Schek Avatar answered Nov 09 '22 15:11

James Schek