Hibernate官方提供的参考手册时,关于Hibernate映射文件的部分,property元素有一个formula属性。该属性的意思是,可以在值对象中定义一个字段,但在映射文件中不映射成对应数据库的字段,而是通过formula属性指定一个sql语句。将sql语句的返回值赋给该字段。当时就觉得这个属性挺有用的。今天做到成绩管理那部分,突然想到需要一个成绩的排名。本来想在数据库中定义一个rank的字段。但是由于排名是不固定的,只能在获取成绩数据的时候动态的决定排名。于是就想起这个属性来了。
在我的值对象score.java中加上一个rank字段,然后在映射文件中加上一下这句代码
1. <property name="rank" formula="(select count(*)+1 from Score s where s.student_score>student_score)"/>
懂sql的都能看明白吧,我说一下需要注意的。首先是sql语句一定要放到一对括号了。然后在引用数据库字段时一定要定义别名,如果不使用别名的话,像我这个sql里,直接写student_score代表当前对象代表的记录行的数据。这个sql语句的意思就是,找出score表里 student_score的数值比当前对象的student_score大的数据的行数。返回这个数加1,就是当前的排名了。
经过这样的写法,在jsp文件中就可以直接使用score.rank获得当前成绩的排名了
1. <property formula="。。。" name="topicCount"/>
以前片面的理解为sql语句必须写在()里,如下面
1. <property name="rank" formula="(select count(*) from score s where s.student_score>student_score)"/>
据个例子说明formula真正的用法,假设user表里面有first_name和last_name属性。在映射的vo里面指定了name属性用于表示两个字段合起来的字符串,使用formula实现如下(数据库用的mysql)
1. <property name="name" formula="concat(first_name,last_name)"/>
假设我们获取了一个id为1的vo实例,那么hibernate就是执行如下sql语句用于取得name的值
1. select concat(first_name, last_name) from user where id=1;
这下子对于formula里的sql语句为什么必须放在括号里应该明白了,因为formula里面的值会作为一条sql语句select和from之间的内容,我们把sql语句放到括号里实际上就是做为一条子查询执行!!! 例如最开始示例的的rank对应的sql语句就应如下样子
1. select (select count(*) from score s where s.score>sc.score) from score sc where sc.id=1;