The problem with JPA/Hibernate (or the future of ORM)

I know, a lot of people are happy to work with JPA and Hibernate. Consider this a post from somebody who thinks things can be improved.

I have a love/hate relationship with Hibernate, for many reasons that I don't want to go into now. Overall I do like Hibernate and think it does a good job but it can be improved in many ways.

I also believe it was a mistake to base the JEE 5 specifications on Hibernate. An object-relational mapping tool has to bridge the gap between ... classes, objects and tables, records. For me Hibernate is a step in the right direction but it's far from perfect. I would have preferred to not have a persistence specification at all in JEE because we're not there yet, but we're doing well.

Object-relational mapping tools have a hard time and not only from all the flack they get. Have you ever looked at how classes and tables are almost each other's opposites? And have you ever wondered how that impacts classes that are mapped with Hibernate?

In database tables - in general - when you follow relationships (foreign keys) you go from general to specific. For example, you follow the foreign key in the ADDRESSES table to the PEOPLE table. But why link an address to a person when other things can have addresses as well? Buildings, companies, customers, hotels, ... .

Maybe you don't have any of these other things in your database, you only have PEOPLE. Ok, then consider what your Address class looks like:

public class Address {
private Person person;
// rest ommitted
}

Maybe you're not worried about this, but why does the Address class have a dependency on the Person class? In a pure object-oriented world that relationship would be determined by a List in the Person class.

public class Person {
private List<Address> addresses = new java.util.ArrayList<Address>();
public void addAddress(Address address) {
addresses.add(address);
}
}

I hear you, the world isn't perfect. But ... there is an Java object-oriented framework that would let you save these kind of objects in a relational database. And you don't have to specify any mapping configuration.

It's called BeanKeeper (here's an introduction article).

First of all, BeanKeeper as it is today can't replace Hibernate or JPA. Since you don't provide a mapping configuration BeanKeeper decides by itself which tables to create for each class. You don't have any control over the relational part. And you can save any object you like, BeanKeeper does the hard work.

Still, for me it's proof that things can be different in object-relational mapping. I believe well-designed object-oriented frameworks start with a set of sound and consistent principles of how classes and tables should or could be mapped. Object-oriented framework don't have to solve every possible problem. And they don't have to support every possible mapping.

By taking a stance that some mapping constructs are not supported it would actually be possible to have better frameworks. Or at least, it would be possible to have a better experience.

A better alternative to Hibernate or JPA would in my opinion have to copy some BeanKeeper ideas. It should be possible to map a one-to-many relationship to a Person class with a List of Addresses. And there will have to be some form of mapping configuration.

Hibernate and JPA are a evolutionary step in the right direction, but they are far from perfect. I hope that some people are working today on better alternatives. If you do please post a comment below.

If you have your own opinion on the future of object-relational mapping let us know!

Average: 1 (1 vote)

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)

Comments

steve zara replied on Thu, 2008/01/17 - 3:38pm

Using a List relationship in persistent classes has been available for a long time in Java, via the JDO specification. The latest version of this (JDO 2.0) is available both in commercial products (such as Kodo) and in the JDO 2.0 RI, a good open source product called JPOX (www.jpox.org). JDO works with both relational and non-relational stores (JPOX works above db4o, for example), and much of the mapping is optional - sensible defaults will be set up for you. JDO has much more transparent use of objects in persistence than JPA.

Peter Maas replied on Thu, 2008/01/17 - 3:48pm

I don't know anything about beankeaper. But your example doesn't make much sense. Both examples can be mapped in JPA/Hibernate:

@Entity
public class Person implements Serializable {
@OneToMany(cascade=CascadeType.ALL)
@JoinColumn(name="ADDR_ID")
private List addresses = new java.util.ArrayList();
public void addAddress(Address address) {
addresses.add(address);
}
}

...

@Entity
public class Address implements Serializable {
//no bidir
}
so what exaclty is your point?

Robin Bygrave replied on Thu, 2008/01/17 - 8:42pm

I too (with p3t0r) am missing your point - perhaps you could clarify? In that this can be mapped as a Unidirectional relationship in which case the Address class does not need an explicit Person property (rather than using a Bidirectional relationship).

Now that said I think there are a few issues with JPA that could be long term issues - from my perspective :).

1. session based architecture - issues with merge/flush/detach

2. JPAQL select clause returning arrays of objects - difficult to support generics in the future.

Cheers, Rob.

Jamie Bisotti replied on Fri, 2008/01/25 - 4:04pm

FWIW, depending on the requirements, Address doesn't even have to be mapped as it's own Entity; it could just be a Value Object and be mapped as a Component of Person.

Jamie

Tonatihu Diaz replied on Sat, 2008/01/26 - 3:58pm

" I also believe it was a mistake to base the JEE 5 specifications on Hibernate"

Why? Hibernate is probably the most successful tool on the subject.

"Have you ever looked at how classes and tables are almost each other's opposites?"

Opposites? I see the object data members and relation fields pretty close to each other. If you are talking about the place in wich you specify the direction of navigation in the object model compared to the relational model, yes, in some cases you're right. Anyway, I don't see a problem here. Can you elaborate more on this?

"BeanKeeper as it is today can't replace Hibernate or JPA. Since you don't provide a mapping configuration BeanKeeper decides by itself which tables to create for each class. You don't have any control over the relational part."

And why do you think it's a better option than Hibernate? And what if there is an existing database schema? I think you need to spend a bit more time with object relational tools, you usually don't choose an ORM tool based only on how easy is to specify mapping metadata. How about performance, integration, community support, docummentation, etc?

"A better alternative to Hibernate or JPA would in my opinion have to copy some BeanKeeper ideas"

Zero-configuration? This is far from being a good idea, how do you customize your data access layer to meet your needs without the flexibility of configuration? All the other features presented in the BeanKeeper main page, are almost completely covered by JPA spec and implementations (Hibernate, TopLink, OpenJPA...), so what other ideas should they copy from BeanKeeper?

"Hibernate and JPA are a evolutionary step in the right direction, but they are far from perfect."

I completely agree.

Post title: "The problem with JPA/Hibernate (or the future of ORM)"

So, where's the problem? Also, I don't see in your post nothing directly related to the future of ORM.

Fred Grott replied on Wed, 2008/01/30 - 7:39pm

 Are you sure you understand what JPA nd Hibernate accomplish? From your riased points I would say the answer is no..

 

Fred Grott(aka shareme) sometimes a JavaZone(JavaLobby) and EclipseZone contributor. Top visited blog on Jroller.com at: http://www.jroller.com/shareme/

Robert Brautigam replied on Tue, 2008/02/05 - 11:19am

Hi guys,

I'm the lead developer of BeanKeeper. I think all of you are right in some sense. I fully agree with the article, that Hibernate is a bitch to use, and I found it is overkill 90% of the time. The article is also correct, that BeanKeeper is not yet mature enough, but we're working on it continously :)

Now BeanKeeper can't do a lot of things Hibernate (and JDO) can, but I also think, all those things (like configuration, different cache mechanisms and whatnot) are not useful, they are most of the time obstacles that need to be overcome. Why would I configure something to use a simple list in a bean in a library that supposed to handle just that? Or configure table names, mappings, etc, in a library which was written to know this kind of stuff anyway?

I also know, that BeanKeeper can't work with already existing tables. Well, in 9 years of Java programming, I've had exactly 1 project in which the schema was fixed in the beginning. Of course your mileage may vary.

To name a few things on top of my head I miss in Hibernate, and why I don't use it:

  • Can't return large result sets (can't page them automatically, you must page it manually with limit/offset/setMaxResults, and that has a lot of problems)
  • Can't return consistent lists, only when keeping a resultset open. What when I need to pass that list to the user interface? What if that list has a million records?
  • You write a webappliction with hibernate. Can you deploy it on load-balanced webservers? Does it require a separate server software to run? Does it still keep locking and visibility guarantees?
  • Session-based persistence handling is counter-intuitive. What happened to the good old save(obj)? :)
  • Does not support schema-evolution.
  • Too complex. Just think of the terminology alone for Hibernate (session, bidirectional, unidirectional relationships, entities, states, detached, etc). Do you really want to know this stuff, when you only want to save an object, query objects?
I think the solution is not to increase the complexity of Hibernate, JDO, etc, and add features until it fills a dvd, and has 6000 pages of documentation. The solution is to create a simple tool, like BeanKeeper, which can co-exist with Hibernate and EJBs, and the developers can decide which library to use on a specific problem.

We are an open project, any feedback is greatly welcome.

Robert.

Robin Bygrave replied on Mon, 2008/03/17 - 1:36am

Hi Robert,

Well, you are making some valid points. I wonder if we can help each other?

- I have a "sessionless" ORM called Ebean (just save/delete - no detach/merge/flush). You can find it a http://www.avaje.org.

- It supports fetching large results with per bean persistence context and/or background fetching. I agree with you in that I find this support an amazing omission from the JPA spec!!

- Ebean does have bi & unidirectional relationships but I think every ORM has to support both... sounds confusing but I think it is generally just explained badly. I hopefully explain bi/unidirectional relationships better it in my (very draft) user guide...

- Ebean simplifies queries ... auto detect the type of join to use, only specify "fetch" joins etc

- Supports generics and you can fetch "partial" objects...

- I'm also developing "Autofetch" support where the object graph usage is "profiled" and can be used so that Ebean can automatically modify a query for optimal performance (specify joins and properties etc). This is going to be very cool IMO.


Q: What is the issue paging large resultsets?

From my view this is where you want to use background fetching. Fetch the first x in foreground, then return continuing the fetch in a background thread.

 

Cheers, Rob.

Robert Brautigam replied on Tue, 2008/04/22 - 12:00pm in response to: rbygrave

Hi Rob,

I took a brief look at avaje, and it looks pretty good. When I have a bit of time, I will read into it further.

On uni-, bi-directional relations. Of course the principles must be there to support them. The question is basically, whether you want the relations to be "smart", in that they know both "ends" of the relation. For example: if there is a Book which has one Author, and the Author object has a list of Books, then you can do two things: If you add a book to the author's book list, you may want the ORM tool to automatically know that that book's author field will need to be altered too. In this case the developer has to know about all kinds of relations, and he has to configure the ORM tool to know which attributes indicate which relations. On the other hand, the ORM tool might persist the object model just the way it is, and leave it up to developer to decide what he has to do in order for the object model to stay consistent. This is what BeanKeeper does, and this way, the developer does not need to configure anything, does not need to know how relations are persisted, he only needs to care about his own object model, which he knows the best anyway.

I think neither one is "better" generally, but maybe BeanKeeper's way is easier.

Handling large result sets is also a problem. When "paging" the traditional way (using limit+offset, or similar things), there are the following problems:
- I don't know the full size (I need to know to display paging widgets for example)
- When asking for the "next" page, the database may have changed, so while I am browsing the data page for page, I may skip some items, and may see items duplicated. This is not acceptable in code.

You may somehow overcome these problems in a single transaction. But what if I calculate a large resultset in a transaction, but I want to present it on a jsp for example. Also what happens when that list re-enters another transaction which needs to iterate on it. I usually need a guarantee that the list I receive will be an unaletered version of the list originally selected. Whether it is large or not, but of course without loading the whole thing into memory.

Well, these are some things BeanKeeper is supposed to solve, and which I didn't find anywhere else.

I'm very open to any discussion on this topic, because I still don't know why these issues are not addressed in current ORM tools. I still fear I'm missing something, although I'm "on board" since EJB 1.1 days.

My email address is posted on http://netmind.hu/beankeeper/support.php, if you want to take this discussion off this forum.

Robert.

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.