论坛首页 Java企业应用论坛

Hibernate中自定义数据库函数

浏览 3246 次
精华帖 (0) :: 良好帖 (13) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2010-09-11   最后修改:2010-09-11
前段日子在用Hibernate在MySQL数据库中查询数据时,出现了如下MySql语法错误:
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函数是这样使用呀~

在网上找了一下,发现还真有不少人遇到这个问题,也有人提供了许多解决办法(奇怪的是这些解决办法基本上是人家外国网站上有人提出的,中文网站上我没见到过,呵呵),其中包括:创建自定义函数、改变查询方式等变通方式。

但也有一个从根本上解决问题的方式:自定义Dialect中的方法,使其支持Mysql中对应的方法。这一点,得从Hibernate对各数据库的本地语言支持说起了。

在Hibernate中,它可以支持大多数主流数据库,在与各数据库结合时,它通过Dialect(即数据库本地化语言)将执行的SQL语句转换为对应数据库中的可执行SQL(因为不同数据库中,SQL会存在一些语法的不一样),所以使用Hibernate与不同的数据库连接时,需要指定对应的Dialect。在我做的这个项目中,使用的是Mysql,因此,也就使用了下面的Dialect:
hibernate.dialect=org.hibernate.dialect.MySQLDialect

但为什么使用了正确的Dialect之后,还是会出现上面这个情况呢?
那是因为上面SQL中的INTERVAL是Hibernate语法中的关键词,它不会认为是Mysql中的关键词,于是在解析SQL时就出错了!
那如何才能自定义一个方法,让它支持这样的语法呢?很简单,看一下上面MySQLDialect中的源码,你就会一下子就明白了:我们只需要重新注册一个方法即可!示例代码如下:
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_interval方法,目的是使它支持MySQL中的date_add函数中的INTERVAL。
然后我们使用这个自定义的Dialect:
hibernate.dialect=com.cloudframework.dialect.MysqlDialect

再然后,将我们上面的SQL改为如下:
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了!
   发表时间:2010-09-14  
不错,很优雅的解决方案。
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics