开发者

For java developers, what is better than Hibernate? [closed]

Closed. This question is opinion-based. It is not currently accepting answers.

Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.

Closed 9 years ago.

Improve this question

I am unsure if there is a better way to develop database-backed applications in Java, but I thought I would ask.

There is a lot I like about Hibernate, but there are lots of problems too. Most of them are not that big of deal when you have as much experience with it as I have, but I think the biggest problem that I run into is one-size fits all lazy-loading model. Absolutely hate it - there has to be something better out there... no?

The reason I hate the lazy-loading model is that while it's convenient to specify what is lazy and not lazy in the configuration file, there are many parts of an application that would prefer lazy-loading in one area and no lazy loading in another. If you want to satisfy both parts of the program, you need put up with lazy-loading and manually load entities and their children... and their children... and so on. This is just bloat that doesn't do anything to solve the real programming problems - like the features that get the project done.

It seems that the loading strategy that you want to use should be independent of the mapping information, but this is not possible (as far as I know) with hibernate other than writing the loading inside of your java code.

Another problem I have with the lazy-loading is that it's not easily predictable when you are going to have problems. I often don't discover lazyloadexceptions until I deploy my application into Tomcat.

It feels even more bloated when these exceptions occur from frameworks - like by Jackson calling into a collection that hasn't loaded yet. Or maybe Spring is accessing a property I never asked it to, so it throws a LazyInitializationException anyway - for no reason other than that their framework touches all of my bean properties.

Anyway, because I can't discover these problems during integration tests... when I discover them in Tomcat, I often have to shut down tomcat, make the changes, recompile, reload tomcat, relogin to 开发者_运维问答my application, go back to the page I was at to see if it's fixed - this is truly a massive pain. It takes so long to fix one of these errors. I feel like it's just getting in the way of what I am actually doing.

In the end, I just feel that details like this really weigh me down. When I look at my day and ask, "What did I produce today?" - I find problems like this really get in the way of me feeling like I accomplished something.

Of course, I can just turn off lazyloading... but then I get absolutely dreadful performance.

Is there a better way? Something that "just does the right thing", performs well and easier to reason about?

Thanks


First of, this has nothing to do with Hibernate. Pretty much any ORM (certainly any JPA provider) implements lazy loading in a similar fashion.

As far as "would prefer lazy-loading in one area and no lazy loading in another" goes, you can override lazy fetching via HQL fetch join if you're using queries. For straight up session.get() there's usually no need to do so (Note - see below), you can just let lazy loading do its magic for you. For that to happen you need to ensure your session stays alive until all requests to entity (its properties / collections / etc...) are done, which is typically achieved via Open Session in View pattern. Spring has a corresponding interceptor as well.

Note: One case where you have to load all entity's dependencies is when you're going to ship it to a remote system (thus making original session unavailable). This is typically handled by marshaller, though.


I agree with others that the notion of better is subjective and context-dependent. True alternatives to JPA / Hibernate are:

MyBatis

It is the most popular SQL templating engine in Java. It externalises SQL statements into XML files, from where they can be loaded by ID or by other means. As a templating engine, MyBatis also supports SQL composition and a slim templating language for loops and branch statements.

jOOQ

This is a popular SQL DSL allowing for typesafe construction of SQL statements directly in Java. Unlike MyBatis, this library encourages embedding SQL in Java, instead of externalising it. (Disclaimer, I work for the vendor)

Other alternatives...

... include SQL-string-centric libraries that ease some of the pain when operating with JDBC directly:

  • JdbcTemplate
  • Apache DbUtils
  • JDBI
  • sql2o
  • persism


Hibernate and other ORMs are designed to make RDBMSs work with object oriented applications. If you are not forced to use an RDBMS I would simply use an ODBMS.

Many ODBMS support implicit lazy-loading via byte-code enhancement, so it is almost impossible to write code that accesses an object that is not properly loaded. You can usually also specify (per code-path) closures that load objects not one-by-one but in batches, which improves performance.

Some ODBMS are:

  • db4o (free, pure Java, but less powerful)
  • Versant (powerful, commercial, Java frontend, C/C++ backend)
  • ObjectStore (commercial)
  • Objectivity (commercial)

ODBMS are sometimes frowned upon, but (in my experience) never by people that have actually used them. I have ODBMS in small and large projects (up to 10TB and 2.000.000.000 objects) and I would never go back to RDBMS.


I don't know about "better" than Hibernate, but if you don't like it there are other alternatives to try:

  1. TopLink (similar to Hibernate)
  2. iBatis
  3. Spring JDBC support (makes JDBC pretty easy, especially if you're already using Spring)


Another ORM library to consider is www.sormula.org. It supports relationships but lazy loading is optional. It was designed to be a simple alternative to the world of complex ORM solutions. I am the author.


One person already mentioned Open Session in View, which will eliminate most if not all of your lazy loading problems (but it brings its own problems).

Open JPA has something called 'fetch groups'. This is basically a named set of fetch settings that you can set before running queries, etc. You would then select the appropriate fetch strategy before running the query (presumably in your service impl). This way, the fetch plan is separate from the mapping. You can configure as many fetch plans as you have use cases. In one fetch plan, a particular association is lazy, but in another, it is eager / JOIN. Seems awesome.

If you've been coding to the JPA spec instead of native Hibernate, the switch to Open JPA could be easy.

If I'm not mistaken, some work is being done to implement fetch groups in Hibernate, but I'm too lazy to google that right now.


Some of the classical ODBMS have also implemented the JPA standard like Versant. So it is easy to try it out. If you want to know how fast they are have a look into the Polepos Benchmark which compares different persistence API's with different implementations with different RDBMS/ODBMS. You can also extend the benchmark easily with your own usecases and run them with all the different persistence technologies.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜