【Problem】


Now, in the development of the so-called multi-storey JavaEE applications, data persistence layer is always essential, and "Automatic" of ORM - Hibernate, and "all-manual-type" of SqlMap - IBatis, equivalent data are Persistence Layer哥俩good. Two brothers have their own advantages and disadvantage also have, in general, Hibernate very very powerful, but many details, the steep learning curve; IBatis quickly and is very simple, but should not cross-database, it is necessary to write a lot of their own SQL, including sub - page and so on. Thus, in many projects, we use simultaneously the two components, and use Spring to unify management.



Recently involved in a project that is used in this way, but encountered a problem not the intention: there is a HibernateDAO contains IBatisDAO and operated Service methods, the process of implementation is always short-selling indicators anomaly; Moreover, this anomaly is only Sybase database in the test out, and there is no problem with MySQL; Even more surprising is a separate test IBatisDAO and HibernateDAO, regardless of what databases are no problem;



Exploring 【】


Null pointer thrown out the location of anomalies in the implementation of a P with Hibernate query object and then query P lazy loaded object set after a link out of.



First reaction: This question, I thought of before come across a Sybase (see Nan-Jing 1: http://liuu.javaeye.com/admin/blogs/288660), it is what Sybase with Hibernate not compatible? However, because of a separate test DAO not have any problem, my denial of such possibility.



Reaction II: IBatis and Hibernate are not mixing up the affairs of the problem? But only in the Sybase encountered, it is strange (no way, This is the project of the production environment), in the end Sybase damned uncomfortable in what to make it.



IBatis and Hibernate mixed use, in fact, relatively easy to configure, on-line also has a lot of examples, largely on the following three steps: as long as the Spring in a common data source, and configure a DataSource using the same transaction manager, and then configure Hibernate and permit the use of external IBatis The transaction management can be. Re-examination of these configurations, nor to see what unusual, and the null pointer for each anomaly is also stubborn dished out, the absolute return ......



Hibernate open the SQL log, I repeatedly place the unusual debugging, look at the implementation of the SQL in the end what have questions:

1, the implementation of the operation of the object P inquiries, OK

2, the implementation of the associated collection of objects P property (including the object M and C) of the query, OK

3, the use of object M, OK

4, using the C object is found that C is still null, FAILED



Appear in the question 4, C Object Query was empty after the Is 2 search results right?

Therefore, I will beat 2 out of the implementation of the SQL database direct connection with the implementation, they found that the normal search results!



Where questions?



郁闷me to turn around and look at the log, suddenly found that the results of 2 queries return only one record! Ah right, just have the two inquiries are the ah, a corresponding object M, the other corresponding to the object C, if only a return, then the C object sure to empty!



Whir, a null pointer causes abnormal found, however, new problems came again, why Hibernate implementation of inquiry 2:00, only a record back then. Summarize the current situation:

1, this problem appeared only in the Sybase and other database of normal

2, HibernateDAO and IBatisDAO alone do not have any problem

3, in the implementation of Hibernate queries, the Executive had IBatis the SQL

4, transaction boundaries designated in the Service of the method, therefore, Hibernate and IBatis implementation of all operations, both in the same connection with a transaction in



Combination of these four, my mind reflected on a Sybase-specific restrictions result set statement: "set rowcount 1", right, is that it should be, it will limit the current to connect all of the query return only the records of not more than 1, and other databases such as MySQL's limit, Oracle's rownum, MSSQL on the top (Sybase's new version also supports the top), only on the current query SQL effective, no side-effects.



To be sure, in the Sybase, in Hibernate query to do this before a IBatis in the implementation of the SQL query operation, the use of set rowcount 1, but not in the query after setting rowcount back, resulting in follow-up query result set are 1, which led to the back of C for abnormal null.



Problem-solving 【】


When the question of focus from behind the abnormal HibernateDAO Department, moved to the implementation of the Service category of the other IBatisDAO before the operation, through the investigation and 11, the soon IBatisDAO achieve the Sybase version of a map configuration file, locate the the culprit: that "set rowcount 1" statement, and in select did not "set rowcount 0" to the rowcount recovery.



In that select statement, insert the words "set rowcount 0", once again testing Service, OK, JUnit Green Rules! !



【Summary】


Looking back, this time encountered a small problem seem to find it costs them big trouble, boils down to the following reasons:

1, error free and illusion: IBatis prepared in SQL error, but in Hibernate implementation of the DAO in the only cause abnormal, leading to always consider the error in the latter, but never the former.

2, lack of communication and code inspections: using IBatis because part of the development of people, some people use Hibernate development, both sides do not understand the two parts of the overall relationship, and a separate DAO test, but test to see such questions, thus in the integrated positioning really difficult problem



In a word, if you are using IBatis development, with or without mixed-use Hibernate, we must pay attention to check the SQL itself, including the current connection settings and restore the property, as well as the differences between different databases.