Reflection 是 Java 程序开发语言的特征之一,它允许运行中的程序对自身进行访问,并能直接操作程序的内部属性。
Hibernate是一个面向Java环境的对象/关系数据库映射工具,基本上,每个表或者视图在hibernate里面都可以对应一个类,在此处,我们通过充分的利用这个类,来实现动态组合查询。
首先我们一起来看看这个函数的源代码:
/**
* 组合查询
* @param object 包含查询条件的对象
* @param firstResult 第一个返回的位置(从0开始)
* @param maxResults 最大返回数
* @param orderField 排序的字段
* @param isAbs 是否正序排列
* @return
* @throws HibernateException
*/
public List queryList(Object object, int firstResult, int maxResults,String orderField ,boolean isAsc) throws HibernateException,IllegalArgumentException,IllegalAccessException,InvocationTargetException {
List list=null;
Class c = object.getClass();
Method method[] = c.getMethods();
try {
Session session = currentSession();
Criteria criteria = session.createCriteria(object.getClass());
for (int i = 0; i < method.length; i++) {
String name = method[i].getName();
if(name.indexOf("getMin")==0){ //大于
String fieldName = name.substring(6, 7).toLowerCase() + name.substring(7);
Object retObj = method[i].invoke(object, null);
if (retObj != null && !retObj.equals(""))
criteria.add(Expression.ge(fieldName, retObj));
continue;
}
if(name.indexOf("getMax")==0){//小于
String fieldName = name.substring(6, 7).toLowerCase() + name.substring(7);
Object retObj = method[i].invoke(object, null);
if (retObj != null && !retObj.equals(""))
criteria.add(Expression.le(fieldName, retObj));
continue;
}
if (name.indexOf("get") != 0 || name.indexOf("getClass") == 0) //如果不是需要的方法,跳出
continue;
String fieldName = name.substring(3, 4).toLowerCase() + name.substring(4);
String returnType = method[i].getReturnType().toString();
Object retObj = method[i].invoke(object, null);
if (retObj != null) { //如果为null,没有赋值,跳出
if (returnType.indexOf("String") != -1){
if(retObj.equals("")) //如果为""的String字段,跳出
continue;
criteria.add(Expression.like(fieldName, "%" + retObj + "%")); //对String的字段,使用like模糊查询
}else
criteria.add(Expression.like(fieldName, retObj));
}
}
if(isAsc)
criteria.addOrder(Order.asc(orderField)); //升序
else
criteria.addOrder(Order.desc(orderField)); //降序
criteria.setFirstResult(firstResult);
criteria.setMaxResults(maxResults);
list = criteria.list();
} finally {
closeSession();
}
return list;
}
假设关系数据库里面有一个物理表,其结构如下:
STAFF(员工表)
列名 |
类型 |
Null |
说明 |
Id(pk) |
VARCHAR2(20) |
NOT NULL |
员工工号 |
name |
VARCHAR2(20) |
NOT NULL |
员工姓名 |
Dept |
INTEGER |
NULL |
员工所属部门(p3) |
Password |
VARCHAR2(20) |
NOT NULL |
密码 |
Post |
INTEGER |
NULL |
员工所属职位(p14) |
Priv |
VARCHAR2(40) |
NOT NULL |
权限字 |
Birthday |
VARCHAR2(20) |
NULL |
生日 |
Active |
VARCHAR2(1) |
NOT NULL |
Y:激活 N:未激活 |
利用工具,生成其相关的hibernate类Staff,其内部包括以下字段:
private java.lang.String id;
private java.lang.String name;
private java.lang.Long dept;
private java.lang.String password;
private java.lang.Long post;
private java.lang.String priv;
private java.lang.String birthday;
private java.lang.String active;
下面,我们就可以利用上面的queryList来进行查询了
例子1:
前台需要一个包含所有人员的List,
那么相关代码如下:
Staff staff=new Staff();
List list=queryList(staff,0,1000,id,true);
例子2:
查询所有姓名里面包含“丁”的人员
那么相关代码如下:
Staff staff=new Staff();
staff.setName=”丁”;
List list=queryList(staff,0,1000,id,true);
例子3:
查询所有姓名包含“丁”,并且处于激活状态的人员
那么相关代码如下:
Staff staff=new Staff();
staff.setName=”丁”;
staff.setActive=”Y”;
List list=queryList(staff,0,1000,id,true);
例子4:
查询所有姓名包含“丁”,并且处于激活状态的人员,同时要求返回的list按照生日进行排序
那么相关代码如下:
Staff staff=new Staff();
staff.setName=”丁”;
staff.setActive=”Y”;
List list=queryList(staff,0,1000,birthday,true,);
对Staff进行一下加工,就可以实现大于,小于的功能,比如我们想实现查询生于1981-09-16以后的人,那么可以在Staff类里面增加如下代码:
private java.lang.String minBirthday;
private java.lang.String maxBirthday;
public java.lang.String getMinBirthday () {
return minBirthday;
}
public void setMinBirthday (java.lang.String minBirthday) {
this.minBirthday = minBirthday;
}
public java.lang.String getMaxBirthday () {
return maxBirthday;
}
public void setMaxBirthday (java.lang.String maxBirthday) {
this.maxBirthday = maxBirthday;
}
例子5:
查询生日在1978年之后,1981年之前的激活状态人员,要求姓名包含“丁”,按照生日降序排列
Staff staff=new Staff();
staff.setName=”丁”;
staff.setActive=”Y”;
staff. setMinBirthday(“1978”);
staff. setMaxBirthday(“1981”);
List list=queryList(staff,0,1000,birthday,false);
至此,应该说介绍的差不多了,或许有人要问,”单表查询,可以如此,那么联表查询怎么办?“其实很简单,在数据库里面建立一个视图就可以了。希望这点经验对大家有用。