五 完善工具类及HQL QBC初步相关
1.无聊的讨论:
在前面我们写了一个工具类:HibernateUtil。其实我们还可以把CRUD操作封装到这个工具类中,并把它们都做成静态的,这样这个工具类就可以直接调用了。但是这样的操作对查询数据可能不是很好,因为它的查询方式很多,除非我们一一考虑这些可能涉及到查询方式,并能以重载的形式进行统一管理。其实我也试想过把这此数据库操作方法进行二次封装,在工具类写成如下形式:
public void operate(int i ){
if(i==1){ 调用更新方法,执行查询操作}
if(i==2){ 调用删除方法,执行查询操作}
if(i==3){ 调用插入方法,执行查询操作}
if(i==4){查询?可指定一个惯用的查询方法,但返回值如何处理,所以建议不在此处写查询,可再写一个查询的统一操作方法来总括所有的查询方法}
}
2.HQL的作用概述
数据库的操作,难点主要集中在查询操作中,而HQL就是专门用来为查询服务的。
3.HQL应用的步骤:
假定我们已有一个Session对象s
>>步骤一,获得Query对象:Query query=s.createQuery(“HQL SELECT Sentence”);
>>步骤二,为参数赋值:query.setXXX();
>>步骤三,获得List对象:LIST list=query.list(); 说明,除了此方法外,Query接口还有一个常用的方法uniqueResult,如果明确查询的结果只有一个,便选择使用此方法。如果查询结果有多个使用此方法会报异常。
>>步骤四,遍历查询结果:即遍历上面list对象。
关于步骤二为参数赋值的问题:比如步骤一中的“HQL Sentence”内容为:from User u where u.name=? and u.password=? and ...,如果这里的?较少可以setXXX(0,”...”); setXXX(1,”...”); 但是如果?较多,就容易把这些设置写错,所以可以采取命令参数的方式来决定后面的setXXX的内容。 比如:from User u where u.name=:uname and u.password=:upass and ... ,这样后面就可以写setXXX(“uname”,”...”);
4.一个细节问题:
在前面我们的实体类为User类,而在实体配置文件中<class name="User">意为它所关联的表为user表(没有指定名称table),但如果是oracle数据库,我们知道它本身就有一张user表,这样就产生了冲突,如何解决这种冲突?一种方法是设定table属性为新的名字(首选方法),另一种方法是加`(数字1前的那个符号),即这样<class name="User" table="`user`">写,这样我们的表还是user表。同样如果属性名与数据库中的关键字产生这种冲突,也可以按此方法解决。
5.分页技术:
query.setFirstResult(200);query.setMaxReslut(10);这两句的意思是符合要求的语句有很多条,我们从第200条取,取出10条。我们知道每种数据库的分页语句是不同的,而Hibernate底层判断使用哪种分页语句就是参照前面配置文件的方言属性。
6.QBC条件查询:
与它相关的是Criteria Interface,Criterion Interface,Expressson Class。其实它的操作和HQL很相似。同样我们假定已有一个Session对象s.
>>步骤一,获得Criteria对象:Criteria criteria = s.createCriteria(User.class); >>步骤二,封装查询条件为一个Criterion对象:Criterion cr = Expression.eq("name", "new name"); (说明Expression继续于org.hibernate.criterion.Restrictions类),所以也可以这样写:Criterion cr=Restrictions.eq("name","new name"); Restrictions类中的封装查询条件的方法都有两个参数:前一个参数是指创建Criteria对象时所使用的参数的属性名,后一个是要与属性名比较的值。比如这里是指User类的name属性是否与“new name”相等 >>步骤三,获得带查询条件的Criteria对象:criteria.add(cr); 执行此步才使这个对象具有一个条件限制的查询操作。
>>步骤四,获得List对象以遍历:List clist = criteria.list(); 补充说明:也可以直接返回一个User对象:User user=(User) criteria.uniqueResult();
特别说明:Criteria对象也具有分页的功能,方式是和上面Query一样。
六 基本应用实例:Dao设计
1.总体设计:设计User对象及相关实体配置文件,工具类(得到一个Session对象),UserDao接口(实现此接口即以操作数据库),编写主配置文件,编写测试类。
2.UserDao的设计,最初我想打算设计成通用Object的操作,后来发现它的Session对象操作都要传递一个对象,就设计成如下形式。内容如下:
package com.asm.dao;
import com.asm.domain.User;
public interface UserDao {
public void saveUser(User user);
public User queryById(int id);
public User queryByName(String name);
public void update(User user);
public void delete(User user);
}
按此设计,意思是此类专门针对User对象的数据库操作,传递User对象,所以后面它的实现类的query相关方法可以直接user = (User) s.get(User.class, name); name为传递的参数,而我们知道操作的是User对象,所以直接可以User.class。 值得一提的是,在JDBC操作中,delete,传递id这种值就可以实现删除,而Hibernate的删除操作,必须传递一个对象,操作过程就是我们通过id查出这个对象,再把这个对象传递给删除方法以供删除。而实事上也可以new一个User对象,并设定的id,然后再把这个对象传递给删除方法。但需要特别注意new出的对象必须完成符合我们通过id查出的对象。
3.这个实例参照前面的相关,基本可以写出。以下几点需要注意:导包:Hibernate包,数据库包;改写配置文件;查询方法的设计;注意事务,特别是“增删改”要注意事务。