浏览 3242 次
锁定老帖子 主题:Hibernate中自定义数据库函数
精华帖 (0) :: 良好帖 (13) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2010-09-11
最后修改:2010-09-11
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了! 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2010-09-14
不错,很优雅的解决方案。
|
|
返回顶楼 | |