1、课程名称: Hibernate查询技术



2、知识点

2.1、上次课程的主要知识点

1、使用Hibernate搭建环境,完成后台数据库的单表操作

2、主键生成方式


2.2、本次预计讲解的知识点

1Hibernate中的QuerySessionCriteria(重要)

2Hibernate中的瞬时,持久和游离态(背)

3Struts2结合Hibernate开发,实现登陆功能(重要)

4、复合主键映射,继承关系映射(了解)



3、具体内容

3.1Hibernate的三种查询方式(掌握)

Hibernate中提供了三种查询方式:

1) Session的查询:按主键查询查询,方法为getload

2) Query的查询:使用HQL语句或SQL语句完成查询

3) Criteria的查询:通过方法和类中属性的关系,来设置查询条件,完成查询。


Sessiongetload方法的区别?

1) 如果没有查询到数据,get会返回null,而load则直接提示错误。

2) 使用load查询时,可能会出现以下错误,因为load方式使用的是懒汉式加载方法。执行load方法时,不立刻查询数据库。当用到查询出的对象的属性时,才加载数据。

org.hibernate.LazyInitializationException: could not initialize proxy - no Session

解决这个异常的方法:

1) 不关连接

2) 不用load,就使用get就可以了。

3.1.1Query查询(重点)

HQL语句不只支持查询功能,还支持修改以及删除功能

public void doRemove(Integer id) throws Exception {
    // 注意,使用Hibernate删除时,必须先查询对象,再删除.
    // HibernateSessionFactory.getSession().delete(findById(id));
    String hql = "DELETE FROM News AS n WHERE n.id = ?" ;
    Query query = HibernateSessionFactory.getSession().createQuery(hql);
    query.setInteger(0, id);
    query.executeUpdate();
}

使用HQL的删除可以不需要先查询,直接删除,支持一次删除多条数据

开发中的选择:

1) 当删除一条数据时,直接使用Session.delete(),因为简单。

2) 批量删除时,使用HQL形式。

public void doUpdate(News vo) throws Exception {
        // HibernateSessionFactory.getSession().update(vo);
        String hql = "UPDATE News AS n SET n.title = ?,n.content = ? WHERE n.id = ?" ;
        Query query = HibernateSessionFactory.getSession().createQuery(hql);
        query.setString(0, vo.getTitle());
        // ....其他参数一样设置
        query.executeUpdate();
    }

开发中的选择:

1) 如果是直接的修改功能,肯定选择Session.update方法

2) 如果是只改某一个字段,使用HQL方式,例如:修改密码


HQL语句不支持添加,但Query支持添加。



针对HQL的查询功能,也支持写SELECT,可以通过编写SELECT,来只查询对象中某一个或某几个属性。


例如:

public List testHQL() throws Exception {
        String hql = "SELECT n.id,n.title FROM News AS n";
        Query query = HibernateSessionFactory.getSession().createQuery(hql);
        return query.list();
    }

经过测试,发现当只查询一个字段时,直接返回该类型的List集合。

但查询两个以上的字段时,返回的是List<Object[]>,每一条查询出的数据,使用Object[]来表示。

public void testHQL() throws Exception {
    List all = ServiceFactory.getINewsServiceInstance().testHQL();
    Object[] value1 = (Object[]) all.get(0);
    System.out.println(value1[1]);
}

这样使用起来很麻烦,因此在Hibernate3.2以上的版本中,提供了一个自动转换类,可以将查询出的Object[],自动转换为pojo 对象。

public List testHQL() throws Exception {
        String hql = "SELECT n.id AS id,n.title AS title FROM News AS n";
        Query query = HibernateSessionFactory.getSession().createQuery(hql);
        query
                .setResultTransformer(new AliasToBeanResultTransformer(
                        News.class));
        return query.list();
    }

一般开发中不会使用这种方式,只有当表中字段过多,但查询时只需要其中几个字段时,才会用到这种方法

Query有一个子接口是SQLQuery,该类支持SQL语句的处理,但实际开发中一般不用。

String sql = "SELECT id AS id,title AS title,content AS content,pub_date AS pubDate FROM news";
        SQLQuery query = HibernateSessionFactory.getSession().createSQLQuery(
                sql);
        query
                .setResultTransformer(new AliasToBeanResultTransformer(
                        News.class));
        return query.list();

但,注意,在Oracle数据库中,为了提高性能,Oracle自动将所有字段名转换为大写,因此如果想要使用,必须将pojo对象的属性也写为大写才能设置。