Hibernate对substring和cast的支持问题

http://blog.sina.com.cn/s/blog_8acd9e4b0102uwev.html

Hibernate对substring和cast的支持问题

问题:要比较日期的范围。。。这是只取MM-dd格式的日期,而数据库中记录的当然是最详细的yyyy-MM-dd的格式。这使用SQL很简单,substring(convert(varchar(10),birthday,120),6,5)

但是放到HQL中就出问题了。。。。

hibernate竟然把它截为了substring(convert(varchar(10),birthday,120))。。。。。然后执行的时候SQL就报错,说substring需要三个参数,我晕阿,后来多处查找问题,竟然无人提到过相关的内容。。。但是hibernate明明支持substring的方法的,在单独处理字符串字段的时候一直都是可以的,后来仔细考虑了下,估计hibernate在处理substring+convert的时候可能处理不好,因为两个都是3个参数的方法,估计hibernate把convert里面的两个参数当作substring的了,于是出了问题,这应该是hibernate的一个bug。

于是后来想用cast+month的方法:

cast(month(birthday) as varchar)。。。结果发现hibernate对cast支持也有问题,竟然报错。。。多处找了下资料,才明白原来hibernate对cast的支持是特别处理的,cast(arg1 as arg2)中arg2的转换类型应该是hibernate类型,而不是数据库中的类型,,我晕倒。。把varchar换成string后就好了,不过发现依然不对。。1月份的话,出来的就是1,不是01。。这样无法对+0的日期格式比较,结果想到了另外两个方法。。。把月份+日期处理成浮点。。月份.日期。。。01-11处理成1.11,11-09处理成11.09,这样就可以比较了,不过比较麻烦。。。但至少问题解决。

后来又想到了另一个方法:

把记录中用户生日的年份取出来,添加到参数的前面,这样convert(varchar(10),birthday,120) >= cast(year(birthday) as string)+'-'+'11-01',这种方法也可以,而且比上面的处理方法简单。。。

再后来想到了一个在hibernate中使用substring+convert的方法,就是对表对象po添加一个新属性,shortbirthday,并在配置文件中如下定义:


         substring(convert(varchar(10),dbirthday,120),6,5)
       

这样就可以在hql中直接使用shortbirthday属性来与参数比较了。。而且hibernate对此是支持的。。。那当然这个又比上面的方法简单了,但是唯一的问题就是,每次查询用户的时候,hibernate都会自动把这个属性查出来,这就影响了查询性能,我只有在查询用户生日的时候才会用到这个属性阿。。。这个让人比较头大,但应该不会影响太大,不过对于要求比较高的我来说。。我不会让这种问题发生的。。。所以我宁愿选择上面的那种方法,虽然稍微麻烦了点,但是不会对别的查询产生影响。

最后,在我以为找到了最佳解决方法的时候,另一个同事找到了一个更好的方法,是目前为止我觉得最好的方法,而且我也觉得应该是这个问题解决得最佳方法,就是灵活运用sql的convert。。。

其实之前我们就一直在考虑如何使用一个sql函数来得到月份+日期的方法,当时大家都被yyyy-MM-dd的格式限定,所以都没有想到,以为是没有办法的,而事实上covert的强大足以解决该问题了。。。

熟悉convert的应该都知道convert的第一个参数的长度也就是决定最终截取格式的长度,并且是从第一个位置开始截取的。。那么我们一直都在convert第三个参数120中考虑问题,从没有想到过别的参数能够直接显示月份+日期的,而事实上它是有参数提供位MM-dd-yyyy格式的。。那么我们利用第一参数的长度和第三个参数的格式就能够得到我们最终需要的月份+日期的格式了。。。这也就避免了hibernate中HQL的尴尬。。。

详细如下:

CONVERT(char(5), GETDATE(), 110)

原文地址:https://www.cnblogs.com/zouhao/p/8325315.html