Hibernate VS iBATIS

对于我们的新产品重新设计,我们正在从 Java 中选择最好的框架。由于考虑的是模型的数据库无关方法,我们正在研究 Struts + Spring 与 iBATIS 或 Hibernate 之间的选项。请建议,这是最好的,因为双方提供持久性。

100969 次浏览

iBATIS and Hibernate are quite different beasts.

The way I tend to look at it is this: Hibernate works better if your view is more object-centric. If however you view is more database-centric then iBATIS is a much stronger choice.

If you're in complete control of your schema and you don't have an extremely high throughput requirement then Hibernate can work quite well. The object model makes for fairly convenient code but at a huge complexity cost.

If you're dealing with a "legacy" database schema where you need to write fairly complicated SQL queries then chances are iBATIS will work better.

HQL (Hibernate Query Language) is another language you'll have to learn and even then you'll probably find cases where you still need to write SQL. What's more, chances are you will at some spend half a day figuring out the right combination of XML, properties, annotations, etc to get Hibernate to generate a performant SQL query.

There is no universal "A is better than B" answer for this question.

Cletus did a great job at summarizing this comparison. Hibernate works well when you control the data model and is more object-centric while iBATIS works well when you need to integrate with an existing database and is more data-centric.

Also I think that Hibernate has a bit more of learning curve. With iBATIS, it's pretty easy to know what is going on while more "magic" happens with Hibernate. In other words, newbies might find iBatis easier to use and to understand.

But I'm not saying that you should prefer iBatis, iBatis and Hibernate are just different as said above.

And by the way, if you go for Hibernate, maybe consider using standardized JPA and EJB 3.0 (JSR-220) object/relational mapping annotations provided by Hibernate Annotations.

if you're already using Spring, I would start with Spring JDBC rather than plunging right into Hibernate or iBatis. If you write your persistence tier in terms of interfaces, you should have no problem switching implementations after you've gotten Hibernate or iBatis under your belt.

There's no reason why it has to be an "all or none" decision. Use what's best for your situation.

Consider what you're trying to achieve. Typically, the Command Query Response Segregation model works well for complex domains.

The reason is that you're trying to do one of two things typically:

  1. Create/Update/Delete some complex domain entities
  2. Run analytic fetch queries (i.e. summation/aggregation queries)

Hibernate works well for case 1 allowing you to just make a POJO and persist/update it. It also does this quickly, unless your domain is quite large.

myBatis is great for fetch queries (case 2) where you just want an answer. Hibernate would attempt to load the entire object graph and you'd need to start tuning queries with LazyLoading tricks to keep it working on a large domain. Conversely if you just want some analytic POJO page, the myBatis implementation of the same query would be trivial.

Because of this, myBatis is faster than Hibernate at SELECTS.

These two cases are the difference between Commands where you want to change the domain data and Responses where you just want to fetch some data.

So, consider these two cases and what your application does. If you have a simple domain and just fetch information, use myBatis. If you have a complex domain and persist entities, use Hibernate. If you do both, consider a hybrid approach. That's what we use on our project that has thousands of entities to keep it under control. ;)

Hibernate is an ORM, meaning (at its most basic level) it maps instances of java objects to actual rows in a database table. Generally, for pojo's retrieved via Hibernate: any manipulations and modifications to these pojo's will appear in the database. Hibernate will generate and execute the relevant SQL at an appropriate time.

Mybatis (at its most basic level) is simply a tool for piecing together and executing SQL that is stored in xml files. It does not map instances of Java objects to rows in a database table, rather it maps Java methods to SQL statements, and therefore it is not an ORM. It can also return pojo's of course, but they are not tied to any kind of a persistence context.

Both tools do a lot more than described above, but one is an ORM and one is not.

The criteria to enable you to choose which one to use, I believe, depends critically on the database model you have to work with.

For example imagine a large sprawling schema, representing some insurance model. Developers are required to retrieve data, and interact with that data in a way that meets the business at hand.

Developer's come on go, and would never be expected to have the requisite business knowledge to write all the sql by hand (which Mybatis would require). Hibernate would suit a scenario like that.

Business analysts define the datamodel, the entities, the relationships and the interactions, as is their expertise. Java developer's then use Hibernate to "walk the model". The business developer's can become very productive quickly without the need to write complicated error prone sql to run on a very complicated schema.

In my expierence, both Hibernate and Mybatis are used regularly on the same project.

Where Hibernate is being used for

  • General C.R.U.D functionality
  • 'Walking' the 'domain object' relational model
  • Session management

and where Mybatis is being used for

  • ad hoc queries
  • kick off (and interact with) stored procedures
  • support very specific or intricate queries
  • support complicated search queries, where search criteria is dynamic, and paging of results

ORM vs persistence framework

Hibernate is object-relation mapping framework (ORM) which maps Java classes to database tables. MyBatis is persistence framework - not ORM. It maps SQL statements to Java methods.

Database schema

Hibernate can create or validate database schema according to your Java model while MyBatis does not have such feature. Also it is convenient for testing environment when you're using in-memory DB. Related discussions:

Cache

Hibernate has first level cache which is impossible to disable. It means that if you query item through ORM and then delete it directly with SQL, it stays in the cache. You can explicitly clear the cache to get the most updated results from database. Related discussions:

Optimistic lock management

Also there are differences for optimistic lock management:

MyBatis doesn't support optimistic concurrency control natively, unlike ORM tools like Hibernate/JPA with the @Version annotation.

Related discussions:

Lazy loading

Hibernate will try to load entire object graph except objects which are marked for lazy loading. myBatis will load data according a SQL query. Lazy loading may improve performance but it may cause connection leaks if it used with <property name="hibernate.enable_lazy_load_no_trans" value="true" /> properties. Related discussions:

Hibernate Session management

Entities operations like saving, updating or deleting are performed via Hibernate Session. It requires good understanding how to implement proper Hibernate Session management strategy to avoid detached entity passed to persist and other phenomenons related to Hibernate.

Sometimes it may take more time trying to understand underlying Hibernate behavior than add a little bit more work and write raw SQL statements for myBatis.

Cascading

Hibernate provides cascading, orphan removal and other features for object graphs while they not present in myBatis - to implement them you'll need to write SQL queries explicitly.

Queries

In myBatis you'll write almost plain SQL queries. Hibernate has multiple options to form query: SQL, HQL, Criteria API. Sometimes it may be suitable to use Criteria API when you have many optional fields in criteria. It would provide more structured approach to form query and maybe avoid related mistakes.