One, hibernate paging hibernate to MSSQL pseudo-paging
Paging is a Web project in a less than a feature, the amount of data can not be fully displayed when it is necessary to use paging technology. I believe you are not familiar with hibernate in the page:
Java code
- Public Query setmaxresults (int maxResults);
- Public Query setfirstresult (int firstresult);
As long as the two methods are called and the parameters are set, Hibernate auto-paging completely masks the underlying database paging technology, which is one of the reasons why many developers like hibernate.
A strange problem was encountered in the development of the project. The database uses SQL Server 2005 and the two parameters above, but each SQL statement sent to the database side is select Top .... Statement. Even if you query section 10w, there is only one select top statement, which can cause doubts about hibernate implementing SQL Server paging. Hibernate's paging method for different databases is encapsulated in the corresponding database dialect, and transformed into the corresponding database paging algorithm by getlimitstring method.
Take the dialect mysqldialect of the common MySQL database as an example:
Java code
- public string getlimitstring (String sql, Boolean hasoffset) {
- return New StringBuffer (sql.length () + )
- . append (SQL)
- . Append (Hasoffset? "Limit?,?": "limit?")
- . toString ();
- }
We use the familiar MySQL limit for paging.
Dialect oracle9idialect for Oracle databases:
Java code
- StringBuffer pagingselect = new StringBuffer (sql.length () +100);
- if (hasoffset) {
- Pagingselect.append ("SELECT * from" (select Row_.*, RowNum rownum_ from (");
- }
- else {
- Pagingselect.append ("select * FROM (");
- }
- Pagingselect.append (SQL);
- if (hasoffset) {
- Pagingselect.append (") Row_ where RowNum <=?) Where Rownum_ >? ");
- }
- else {
- Pagingselect.append (") where RowNum <=?");
- }
Complete pagination with Oracle's rownum combined with three-tier nested queries. This three-tier is Oracle's most classic and efficient paging algorithm.
However, the dialect sqlserverdialect for SQL Server:
Java code
- public string getlimitstring (string queryselect, int offset, int limit) {
- if (offset > 0) {
- throw New Unsupportedoperationexception ( "Query result offset is not supported");
- }
- return New StringBuffer (queryselect.length () + 8)
- . Append (Queryselect)
- . Insert (Getafterselectinsertpoint (queryselect), "top" + limit)
- . toString ();
- }
Rub the eyes, then rub, yes, only a top statement appears. This means that if you query the data on page 10w, you need to extract all the data from the first 10w pages. Hibernate paging for SQL Server is pseudo-paging, so as the amount of data increases and users complain that the system is slow and the programmer complains that hibernate performance is low, the DBA complains that the developer SQL is too shallow.
Do not know the Hibernate development group, for what is not currently or the situation does not really provide SQL Server paging technology, then we implement it ourselves.
Dialect Category:
Java code
- Public class Sqlserver2005dialect extends Sqlserverdialect {
- /**
- *
- * Do I need to bind the limit parameter?
- *
- * When using top in SQL Server, you cannot use parameters to represent top bars, while using row_number () you need to supply the limit parameter
- */
- private Threadlocal<boolean> supportsvariablelimit = new threadlocal<boolean> ();
- Public Sqlserver2005dialect () {
- Registerfunction ("Bitand", new Bitandfunction ());
- Registerfunction ("Bitxor", new Bitxorfunction ());
- Registerfunction ("Bitor", new Bitorfunction ());
- Setsupportsvariablelimit (false);
- }
- /**
- *
- * <p>
- * Sets whether the limit parameter is bound first.
- * </p>
- *
- * @param First
- */
- private void Setsupportsvariablelimit (boolean first) {
- This.supportsVariableLimit.set (boolean.valueof (first));
- }
- /**
- *
- * <p>
- * Gets the location of the SELECT clause in SQL.
- * </p>
- *
- * @param sql
- *
- * @return int
- */
- protected static int getsqlafterselectinsertpoint (String sql) {
- int selectindex = Sql.tolowercase (). IndexOf ("select");
- int selectdistinctindex = Sql.tolowercase (). IndexOf ("SELECT distinct");
- return Selectindex + ((Selectdistinctindex = = Selectindex)? : 6);
- }
- Public Boolean supportslimitoffset () {
- return true;
- }
- /*
- * Hibernate after obtaining the limit String (the limit clause has been added), if this method returns True,
- *
- * Additional parameter values (Row_number () range) are added (the policy may be: There is offset set two parameter value, no parameter value set)
- */
- Public Boolean supportsvariablelimit () {
- return ((Boolean) this.supportsVariableLimit.get ()). Booleanvalue ();
- }
- Public Boolean usemaxforlimit () {
- return true;
- }
- /**
- * Home Top, later with Row_number
- */
- Public string getlimitstring (string query, int offset, int limit) {
- Setsupportsvariablelimit (Offset > 0);
- if (offset = = 0) {
- return New StringBuffer (query.length () + 8). Append (query). Insert (
- Getsqlafterselectinsertpoint (query), "top" + limit)
- . toString ();
- }
- return getlimitstring (query, offset > 0);
- }
- Public string getlimitstring (String sql, Boolean hasoffset) {
- int orderbyindex = Sql.tolowercase (). LastIndexOf ("Order by");
- if (Orderbyindex <= 0) {
- throw New Unsupportedoperationexception (
- "must specify ' ORDER BY ' statement-to-support-limit operation with offset in SQL Server 2005");
- }
- String Sqlorderby = sql.substring (Orderbyindex + 8);
- String Sqlremoveorderby = sql.substring (0, Orderbyindex);
- int insertpoint = getsqlafterselectinsertpoint (sql);
- return New StringBuffer (Sql.length () + + )
- . Append ("with Temppagination as (")
- . Append (Sqlremoveorderby)
- . Insert (
- Insertpoint + ,
- "Row_number () over (ORDER by" + Sqlorderby
- + ") as RowNumber,")
- . Append (
- ") SELECT * from temppagination where rownumber>? and rownumber<=? ")
- . toString ();
- }
- }
Finally configure dialect to use your own Sqlserver2005dialect class when configuring Hibernate in Hibernate.cfg.xml
<property name= "dialect" > com.common.sqlserver2005dialect</property> or in an integrated configuration file with spring
<prop key= "Hibernate.dialect" >com.common.SQLServer2005Dialect</prop>
When paging, you can achieve very good efficiency.
The first page uses the top page, and later the first page of the Row_number page the above query requires that SQL must contain a sort clause.
This is only the problem that SQL Server encountered during the project process, and you will not experience this problem if you use Mysql,oracle.
Troubleshoot hibernate for SQL Server paging slow