Hibernate直接执行SQL语句

时间:2022-09-24 08:38:46

又到周六时间了。我有一次帮*局开发项目时,有这么一个需求,在做统计报表的时候,我在Oralce数据中创建了一个视图,按管辖单位进行了分组,计算了每个管辖单位涉案人数及接警人数等,数据库视图倒是出来了,但是前台需求一个时间查询,也就是客户可以按时间检索,可是视图中,只能加上固定的时间进行where查询,但不能把时间字段加进去,一旦把时间字段加进去的话,就变成了按时间分组,原本管辖单位是六十来个,按时间分组就变成了上千上万条信息,这是不合要求的,这样根本无法统计出每个管辖单位的数据,因为数据库大,在查询时,性能也变慢。

在数据库中,可以写在where中写固定时间,一旦生成视图,在后台调用视图时,将无法再改变,在这里,就应该使用反射机制动态映射实体类,把SQL语言放在Hibernate中,直接执行语句,动态的把前台检索的条件传到后台中的SQL语句中的where中,然后Hibernate进行连接数据库并检查。

大家都知道,Hibernate主要还是使用Hql语句映射实体类进行与数据库关联。也就是说,你数据库表中的字段,都是要在实体类中映射对应的,要不然,就会报无法执行“could not execute query” 或是报‘标示符无效’等错误。因此,我们在这就要使用到反射进行映射一个数据库不存在的数据。说了这么多,我贴个代码段吧。

public List<V_WEB_AJTJ> getAJTJ(String paramList,String bjsjTime,int startRow,
			int endRow) {
		String sql = "select *  from (SELECT nvl(V.dwjc,'空') as gxdw,nvl(v.dwfj,'空') as GXFJ," +
				"sum(decode((case when(v.zpje >= 600) then v.ajlx end),'案件',1,0)) as CAS," +
				"sum(decode((case when(v.zpje < 600) then v.ajlx end),'案件',1,0)) as ZAAJ," +
				"count(case when(v.ajlx='案件')then v.ajlx end) as ZS" +
				" FROM VJJDB_ZPJQB V " +
				" where 1=1 "+bjsjTime+
				" group by v.dwjc,v.dwfj" +
				" order by count(case when(v.ajlx='案件')then v.ajlx end) desc) Test where 1=1 "+ paramList ;
		SQLQuery query = getSession().createSQLQuery(sql);
		query.addEntity("V_WEB_AJFXTJ",V_WEB_AJTJ.class);
		query.setFirstResult(startRow);
		query.setMaxResults(endRow);
		
		return query.list();
	}

上面代码是一段查询方法,直接把SQL语句,bjsjTime是前台传到后台Action中的时间条件。paramList也是前台传到后台的条件与值,这样用String进行字符串拼接,使用成为一个可执行的SQL语句,然后把这个SQL语句扔到Hibernate工厂里进行执行:sessionfactory.getcurrentSession().createsQLQuery(sql),返回的是SQLQuery。然后我们用addEntity("", )给他反射映射一个实体类,字段就是前台要查询的条件,大家可以从我上面的代码中可得知,我的条件都是sum函数计算出来的别名,这个是在数据库中没有的字段,如果使用HQL语句的话,就必须对应数据库中有的字段才行。上面虽然使用了。class反射映射,但实体类还是要有的,

@Entity
@Table(name="V_WEB_AJFXTJ")
public class V_WEB_AJTJ {
	@Id
	@Column(name="GXDW")
	private String GXDW;	//管辖单位
	@Column(name="GXFJ")
	private String GXFJ;	//管辖*
	@Column(name="CAS")
	private int CAS;	//成案数
	@Column(name="ZAAJ")
	private int ZAAJ;	//治安案件
	@Column(name="ZS")
	private int ZS;	//总数
//get/set....
上面对应的数据库表在数据库中是不存在的。表不存在,那字段自然也不存在,只是在他编译完后我们反射得到我们想要的而与,虽然这里说得抽象,但可以慢慢体会。步骤也就这两步而与,一个是Hibernate执行语句,一个是实体类,另外我再贴一下分页要用到的查询总数的代码,和查询语句是一样的,只是返回的是Int类型而与。

public int getCount(String paramList,String bjsjTime) {
		String sql = "select *  from (SELECT nvl(V.dwjc,'空') as gxdw,nvl(v.dwfj,'空') as GXFJ," +
				"sum(decode((case when(v.zpje >= 600) then v.ajlx end),'案件',1,0)) as CAS," +
				"sum(decode((case when(v.zpje < 600) then v.ajlx end),'案件',1,0)) as ZAAJ," +
				"count(case when(v.ajlx='案件')then v.ajlx end) as ZS" +
				" FROM VJJDB_ZPJQB V " +
				" where 1=1 "+bjsjTime+
				" group by v.dwjc,v.dwfj" +
				" order by count(case when(v.ajlx='案件')then v.ajlx end) desc) Test where 1=1 "+ paramList ;				
		SQLQuery query = getSession().createSQLQuery(sql);
		query.addEntity("V_WEB_AJFXTJ",V_WEB_AJTJ.class);

		return query.list().size();
	}
上面的语句就是返回一个查询数据的总数量,这两个查询都是Dao中的方法,我们在Action调用Service再调用这个方法,得到我们前台想要的结果。