Hibernate数据库查询


Hibernate提供了两种数据查询方式,HQL和QBC。不过,因为Hibernate将精力更加集中在HQL查询语言上,所以QBC的功能还未做到尽善尽美。因此,在实际开发中,建议还是采用Hibernate官方推荐的查询封装模式HQL。

Hibernate的配置

应该是与JEECG工程的dbconfig.properties中配置的数据库一同进行查询。
这篇博客说的很详细。hibernate的配置文件是需要自己动手创建的?待确认

HQL

HQL,全称Hibernate Query Language(Hibernate 查询语言),是hibernate提供的完全面向对象的查询语言,因而支持继承、多态等特征。Hibernate是一种ORM框架(Object Relative DateBase-Mapping)。

对查询条件进行了面向对象封装,负责在Java对象与关系数据库之间建立某种映射,以实现直接存取Java对象。更通俗地讲,直接把对象保存到数据库,直接从数据库中取出对象。类似于MVC中的数据持久层,即工程程序中的DAO层。正因为如此,HQL虽然与SQL在一定程度上类似,但却不依赖于数据库表—— 我们在HQL中使用类名,而不是表名(在查询语句中将sql中的表名替换成了sql中的持久化类名,因为hibernate机制是基于对象进行查询的),所以HQL是数据库独立的查询语言。

HQL查询是需要SQL的基础的,因为还是要写少部分的SQL代码。

HQL与SQL(Struct Query Language,结构化查询语言)的区别
HQL查询的是对象以及对象的属性【因此区分大小写!】,而不是表
SQL: 查询的是表以及列【不区分大小写】

HQL查询步骤

  1. 获得HibernateSession对象
  2. 编写HQL语句
  3. 调用Session的createQuery方法创建查询对象
  4. 如果HQL语句包含参数,则调用Query的setXxx方法为参数赋值
  5. 调用Query对象的list等方法返回查询结果。

示例如下:

private void query(){
        Session session = HibernateUtil.getSession();
        Transaction tx = session.beginTransaction();
        //HQL例句
        String hql="from Admin as admin where admin.aname=:name";
        String hql="select b.bookName as ss from Book b";
        
        //用HQL语句创建Query对象,Query对象使用setXxx方法为HQL语句的参数赋值,并调用list方法访问查询的全部实例
        List<Object[]> list = session.createQuery("select distinct p from Person p where p.name=:name").setString("name", "chenssy").list();
 
 		//遍历数组类型的查询结果
 		for (Object[] b : list) {
            System.out.println(Arrays.toString(b));
        }
        //遍历List list查询结果
        for (Iterator iterator = list.iterator();iterator.hasNext();) {
            Person p = (Person) iterator.next();
            System.out.println("id="+p.getId()+",age="+p.getAge());
        }
        session.close();
    }

HQL语法格式

完整语法

//基本语法如下,注意这里查询的都是JAVA类对象
select "对象.属性名"
from "对象名"
where "条件"
group by "对象.属性名" having "分组条件"
order by "对象.属性名"

查询对象的所有信息

select * from Employee 
//等价于
from Employee

根据“条件”查询对象的所有属性

在where "条件"输入查询条件,并使用from的缩略语句。

//语句格式
from + 类名 + 类对象 + where + 对象的属性
//若语句中不需要使用“对象的属性”,如“where + 对象的属性”,则可以直接
from + 类名

** 若hql语句中不需要使用“对象的属性”(如“where + 对象的属性”),则from后可以只写类名,而不用声明类对象——即from后是否声明对象,要看其后的where中是否需要用到该对象**

//例句
from Person
from Employee emp where emp.sex="男"
from User user where user.name=:name
from User user where user.name=:name and user.birthday < :birthday

根据条件查询对象的指定属性

此种情况时,需要该对象的类应具有对应的构造方法,如下例所示。

//此时Employee对象必须要有构造方法public Employee(String empname, String job);
select new Employee (empname,job) from Employee

HQL语句的生成

使用StringBuffer来输出需要的HQL语句。

StringBuffer buffer = new StringBuffer("from Employee where 1=1");

//拼接HQL
if (ee.getEmpname() != null && ee.getEmpname().length() > 0) {
    buffer.append(" and empname like :empname");
}

if (ee.getSalary() != null && ee.getSalary() > 0) {
    buffer.append(" and salary> :salary");
}

if (ee.getJob() != null && ee.getJob().length() > 0) {
    buffer.append(" and job= :job");
}
    
//输出HQL语句
buffer.toString();

这篇博客这篇中有很多代码示例。

区分大小写,关键字不区分大小写。详见这篇博客

取得结果

加入这篇博客

Session

Session是Hibernate最重要的对象,Session维护了一个连接(Connection),只要使用Hibernate操作数据库,就需要用到Session对象。

通过主键来查询数据库的记录,从而返回一个JavaBean对象
session.get(javaBean.class, int id); 【传入对应的class和id就可以查询】
session.load(javaBean.class, int id); 【支持懒加载】

QBC

QBC,全称query by criteria,标准化对象查询。直译来说就是通过criteria对象进行查询,将Criteria作为一种对象化的查询封装模式。
与HQL相比,QBC查询就是完全的面向对象查询。其以对象的方式进行查询,将查询语句封装为对象操作,可读性好,符合java程序员的编程习惯。
Hibernate 在运行期会根据Criteria 中指定的查询条件(即criteria.add中添加的查询表达式)生成相应的SQL语句。我们可以打开Hibernate 的show_sql 选项来观察Hibernate在运行期生成的SQL语句。

在JEECG 4.0 教程中看到如下代码,所以CriteriaQuery 的作用是为了最终生成查询要使用的Hql语言,从而节省了学习hql语言的时间?

CriteriaQuery cq = new CriteriaQuery(TSUser.class, dataGrid);
//查询条件组装器
HqlGenerateUtil.installHql(cq, user);

Criteria查询表达式

在Hibernate的QBC中,Criteria是一个用来存放查询数据语句的容器类,具体的查询语句以Expression对象来描述,然后再通过Criteria.add方法将代表一条条查询语句的expression对象添加到Criteria容器中。在Hibernate3中,引入了Restrictions类作为Expression的替代,以后的版本,不再推荐使用Expression
Restrictions类的使用方法和Expression的方法一致。注意,在查询条件中,Hibernate提供了一个Example查询,当查询条件比较多的时候,可以用Example查询来简化代码,使用方法如下:
TUser user=new TUser();
user.setLoginName(“hulei”);
user.setPassword(“hulei”);
Criteria ct =HibernateSessionFactory.getSession().createCriteria(TUser.class);
ct.add(Example.create(user));
return ct.list();
Criteria ct 中添加多种检索条件可以看这篇博客

Expression

针对SQL 语法,Expression提供了对应的查询限定机制,具体如下:

数据字段与属性值间的比较

field指数据库中的数据字段,比如"id=007"中的"id"就是一个数据字段。

  • Expression.eq对应SQL中“field = value”表达式。
    比如,Expression.eq("name","Erica")对应SQL中的“name = Erica”表达式。
  • Expression.allEq 相当于多个Expression.eq关系的叠加。参数为一个Map对象,其中包含了多个“属性-值”对应关系。
  • Expression.gt 对应SQL中的 “field > value ” 表达式
  • Expression.ge 对应SQL中的 “field >= value” 表达式
  • Expression.lt 对应SQL中的 “field < value” 表达式
  • Expression.le 对应SQL中的 “field <= value” 表达式
  • Expression.between 对应SQL中的 “between” 表达式
    比如,要查询年龄(age)位于13到50区间内的数据,Expression.between("age",new Integer(13),new Integer(50));

数据字段间的比较

  • Expression.in 对应SQL中的 ”field in …” 表达式
  • Expression.eqProperty 用于比较两个字段间的属性值,对应SQL中的“field = field”。

比如,比较两个id,Expression.eqProperty("TUser.groupID","TGroup.id");

  • Expression.gtProperty 对应SQL中的“field > field”。
  • Expression.geProperty 对应SQL中的“field >= field”。
  • Expression.ltProperty 对应SQL中的“field < field”。
  • Expression.leProperty 对应SQL中的“field <= field”。
  • Expression.and,如:
Expression.and(
 Expression.eq("name","Erica"),
 Expression.eq("sex",new Integer(1))
 );
  • Expression.or or关系组合,如:
 Expression.or(
 Expression.eq("name","Erica"),
 Expression.eq("name","Emma")
 );

Expression.sql 作为补充,本方法提供了原生SQL语法的支持。我们可以通过这个方法直接使用SQL语句限定查询条件。下面的代码返回所有名称以“Erica”起始的记录:

Expression.sql(
“lower({alias}.name) like lower(?)”,
"Erica%",
Hibernate.STRING
);

其中的“{alias}”将由Hibernate在运行期使用当前关联的POJO别名替换。
注意Expression 各方法中的属性名参数(如Express.eq中的第一个参数),这里所谓属性名是POJO中对应实际库表字段的属性名(大小写敏感),而非库表中的实际字段名称。

将配置好的Expression放入criteria

criteria.add(Expression.eq("name","Erica"));
criteria.add(Expression.eq("sex",new Integer(1)));
上面两条代码就可以看做SQL语句中的“Select * from t_user where name=’Erica’ and sex=1”的封装,自认

如果还想看更多的例子,可以看这篇博客

Restrictions

在Hibernate3中,引入了Restrictions类作为Expression的替代,以后的版本,不再推荐使用Expression

Example查询

在查询条件中,Hibernate提供了一个Example查询,当查询条件比较多的时候,可以用Example查询来简化代码,使用方法如下:

 TUser user=new TUser();
 user.setLoginName("hulei");
 user.setPassword("hulei");
 Criteria ct=session.createCriteria(TUser.class);
 ct.add(Example.create(user));
 return ct.list();

复合查询

Criteria查询可以嵌套Criteria来实现复合查询,比如

 Criteria ct = session.createCriteria(TUser.class);
 //下面的语句嵌套了一个Criteria查询,这里的addresses是TUser的属性
 Criteria ctAddress = ct.createCriteria("addresses");
 ctAddress.add(Expression.like("address","%shanghai%"));
 List list = ct.list();

使用CriteriaQuery查询数据

CriteriaQuery通过面向对象化的设计,将数据查询条件封装为一个对象。简单来讲,CriteriaQuery可以看作是传统SQL的对象化表示。CriteriaQuery类中已经使用了Restrictions来替代Expression。

eq(String keyname, Object keyvalue)

设置“相等”查询条件,keyname字段名,keyvalue字段值criterionList.addPara(Restrictions.eq(keyname, keyvalue));

官方文档给出的使用示例:cq.eq("attn", user.getUserName());

notEq(String keyname, Object keyvalue)

设置“不等”查询条件,criterionList.addPara(Restrictions.ne(keyname, keyvalue));

like(String keyname, Object keyvalue)

criterionList.addPara(Restrictions.like(keyname, keyvalue));

gt(String keyname, Object keyvalue)

设置>查询条件,criterionList.addPara(Restrictions.gt(keyname, keyvalue));

lt(String keyname, Object keyvalue)

设置<查询条件,criterionList.addPara(Restrictions.lt(keyname, keyvalue));

le(String keyname, Object keyvalue)

设置<=查询条件,criterionList.addPara(Restrictions.le(keyname, keyvalue));

ge(String keyname, Object keyvalue)

设置>=查询条件,criterionList.addPara(Restrictions.ge(keyname, keyvalue));

between(String keyname, Object keyvalue1, Object keyvalue2)

设置区间查询条件,

if (!keyvalue1.equals(null) && !keyvalue2.equals(null)) {
			c = Restrictions.between(keyname, keyvalue1, keyvalue2);
		} else if (!keyvalue1.equals(null)) {
			c = Restrictions.ge(keyname, keyvalue1);
		} else if (!keyvalue2.equals(null)) {
			c = Restrictions.le(keyname, keyvalue2);
		}

in(String keyname, Object[] keyvalue)

criterionList.addPara(Restrictions.in(keyname, keyvalue));

官方文档给出的使用示例:cq.in("TBPrjstatus.code", status);

isNull(String keyname)

criterionList.addPara(Restrictions.isNull(keyname));

官方文档给出的使用示例:cq.isNull("attn");

isNotNull(String keyname)

criterionList.addPara(Restrictions.isNotNull(keyname));

put(String keyname, Object keyvalue)

保存查询条件,不太明白什么意思= =待查map.put(keyname, keyvalue);

使用map.put查询条件组装器 多字段排序

CriteriaQuery cq = new CriteriaQuery(MlCashRecordEntity.class, dataGrid);

Map<String,Object> map = new HashMap<String,Object>();
map.put("createDate", "desc");  
cq.setOrder(map);  
          
Map<String,Object> map1 = new HashMap<String,Object>();
map1.put("quantity", "desc");  
cq.setOrder(map1);   

getResults()

取得查询数据的结果,代码如下。自认,待确认

public List<?> getResults() {
		return results;
}

网上博客找的CriteriaQuery使用示例

 int i = Integer.parseInt(curentPage);
 dataGrid.setPage(i);
 dataGrid.setSort("createDate");
 dataGrid.setOrder("desc");
 
 //Hibernate会在运行期根据Criteria中指定的查询条件(下面代码中通过criteria.add方法添加的查询表达式)生成相应的SQL语句
 CriteriaQuery cq = new CriteriaQuery(MlCashRecordEntity.class, dataGrid);
 cq.eq("categroyId", categroyId);
 cq.add();
 
 //获取查询结果,结果的数据类型为MlCashRecordEntity
 List<MlCashRecordEntity> mlCashRecordEntities1 = systemService.getListByCriteriaQuery(cq, true);

CriteriaQuery添加查询条件的实现原理

CriteriaQuery是通过封装Criterion类来实现的。

public void add() {
		for (int i = 0; i < getCriterionList().size(); i++) {
			add(getCriterionList().getParas(i));
		}
		getCriterionList().removeAll(getCriterionList());
}
public void add(Criterion c) {
		detachedCriteria.add(c);
}

使用CriteriaQuery查询获取查询结果

public ResponseMessage<Map<String,Object>> list(int pageSize,JeecgDemoEntity entity,HttpServletRequest request, HttpServletResponse response, DataGrid dataGrid) {

		InterfaceRuleDto interfaceRuleDto = InterfaceUtil.getInterfaceRuleDto(request, InterfaceEnum.jeecgdemo_list);
		if(interfaceRuleDto == null){
			return Result.error("您没有该接口的权限!");
		}

		//DataGrid dataGrid用来存储查询结果,如最后三行代码所示
		CriteriaQuery query = new CriteriaQuery(JeecgDemoEntity.class, dataGrid);

		InterfaceUtil.installCriteriaQuery(query, interfaceRuleDto, InterfaceEnum.jeecgdemo_list);
		org.jeecgframework.core.extend.hqlsearch.HqlGenerateUtil.installHql(query, entity, request.getParameterMap());
		query.setCurPage(pageNo<=0?1:pageNo);
		query.setPageSize(pageSize);
		
		//设置查询条件
		query.addOrder("createDate", SortDirection.desc);
		
		//将前面设置的查询条件添加入DetachedCriteria中
		query.add();
		
		//使用CriteriaQuery 查询,并获取查询结果
		this.jeecgDemoService.getDataGridReturn(query, true);
		
		Map<String,Object> resultMap = new HashMap<String, Object>();
		resultMap.put("data", dataGrid.getResults());
		resultMap.put("total", dataGrid.getTotal());
		return Result.success(resultMap);
}

版权声明:本文为u010804417原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。