Hibernateでのカスタムデータベース関数

7495 ワード

http://hellohank.iteye.com/blog/760783ちょうど自分がプロジェクトで出会った
 
先日、MySQLデータベースでHibernateを使用してデータを照会したところ、次のようなMySql構文エラーが発生しました.
Javaコード
 
收藏代码
  • Hibernate: select count(*) as col_0_0_ from customer customer0_ where 1=1 and (customer0_.primary_customer_id is null) and (birthday between date_add(curdate(), INTERVAL -22, DAY) and curdate())   
  • 2010-09-11 02:44:23,281 WARN [org.hibernate.util.JDBCExceptionReporter] -    
  • 2010-09-11 02:44:23,281 ERROR [org.hibernate.util.JDBCExceptionReporter] -   
  • Hibernate: select count(*) as col_0_0_ from customer customer0_ where 1=1 and (customer0_.primary_customer_id is null) and (birthday between date_add(curdate(), INTERVAL -22, DAY) and curdate())
    2010-09-11 02:44:23,281 WARN [org.hibernate.util.JDBCExceptionReporter] - <SQL Error: 1064, SQLState: 42000>
    2010-09-11 02:44:23,281 ERROR [org.hibernate.util.JDBCExceptionReporter] - <You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ' DAY) and curdate())' at line 1>
    

    そこでMysqlの文法を調べてみると、このような書き方は間違いないでしょう.date_add関数はこのように使いますね~ネットで探してみると、本当に多くの人がこの問題に直面していることに気づきました.多くの解決策を提供している人もいます(不思議なことに、これらの解決策は基本的に外国のサイトで提案されているもので、中国語のサイトでは見たことがありませんが、ほほほ)には、カスタム関数の作成、クエリーの変更などのトランスフォームが含まれています.しかし、根本的に問題を解決する方法として、Mysqlで対応する方法をサポートするDialectの方法をカスタマイズする方法もあります.この点は、Hibernからateは各データベースのローカル言語サポートについて述べた.Hibernateでは、ほとんどの主流データベースをサポートし、各データベースと結合するときに、Dialect(データベースローカライズ言語)を使用して、実行されたSQL文を対応するデータベースの実行可能SQLに変換します.(SQLはデータベースによって文法の違いがあるので)Hibernateを使用して異なるデータベースに接続する場合は、対応するDialectを指定する必要があります.私が作ったこのプロジェクトではMysqlを使用しているので、次のDialectも使用しています.
    Javaコード
     
    收藏代码
  • hibernate.dialect=org.hibernate.dialect.MySQLDialect  
  • hibernate.dialect=org.hibernate.dialect.MySQLDialect
    

    しかし、なぜ正しいDialectを使った後、このような状況になったのでしょうか.それは上のSQLのINTERVALがHibernate文法のキーワードなので、Mysqlのキーワードとは思えないので、SQLを解析するときにエラーが発生しました!では、このような文法をサポートする方法をカスタマイズするにはどうすればいいのでしょうか.簡単です.上のMySQLDialectのソースコードを見てみると、私たちは方法を再登録するだけでいいことがわかります.サンプルコードは次のとおりです.
    Javaコード
     
    收藏代码
  • package com.cloudframework.dialect;   
  •   
  • import org.hibernate.Hibernate;   
  • import org.hibernate.dialect.MySQLDialect;   
  • import org.hibernate.dialect.function.SQLFunctionTemplate;   
  •   
  • public class MysqlDialect extends MySQLDialect {   
  •   
  •     public MysqlDialect() {   
  •         super();   
  •         registerFunction("date_add_interval", new SQLFunctionTemplate(Hibernate.DATE, "date_add(?1, INTERVAL ?2 ?3)"));   
  •     }   
  •   
  • }  
  • package com.cloudframework.dialect;
    
    import org.hibernate.Hibernate;
    import org.hibernate.dialect.MySQLDialect;
    import org.hibernate.dialect.function.SQLFunctionTemplate;
    
    public class MysqlDialect extends MySQLDialect {
    
    	public MysqlDialect() {
    		super();
    		registerFunction("date_add_interval", new SQLFunctionTemplate(Hibernate.DATE, "date_add(?1, INTERVAL ?2 ?3)"));
    	}
    
    }
    

    上のコードではdate_を定義しましたadd_MySQLのdate_をサポートするためのIntervalメソッドadd関数のINTERVAL.次に、このカスタムDialectを使用します.
    Javaコード
     
    收藏代码
  • hibernate.dialect=com.cloudframework.dialect.MysqlDialect  
  • hibernate.dialect=com.cloudframework.dialect.MysqlDialect

    次に、上のSQLを次のように変更します.
    Javaコード
     
    收藏代码
  • select count(*) as col_0_0_ from customer customer0_ where 1=1 and (customer0_.primary_customer_id is null) and (birthday between date_add_interval(curdate(), -22, DAY) and curdate())  
  • select count(*) as col_0_0_ from customer customer0_ where 1=1 and (customer0_.primary_customer_id is null) and (birthday between date_add_interval(curdate(), -22, DAY) and curdate())
    

    そしてまた実行すればOK!