Session操作过程中的pojo对象存在三种状态:
1) 瞬时态:该对象在数据库中没有对应的数据
2) 持久态:数据库中存在该对象对应的数据,同时操作该对象的Session也存在。
3) 游离态:数据库中包含该对象对应的数据,但操作此对象的Session已经不存在或被关闭了。
三种状态之间的转换:
瞬时 à 持久:save(),saveOrUpdate()
持久 à 瞬时:delete()
持久 à 游离:close()
游离 à 持久:update(),saveOrUpdate()
针对持久态对象,Hibernate还存在以下两个特点:
1) 持久态对象,在同一Session中只存在同一个。
a) 如果连接不关闭,多次查询同一条数据,只返回同一个对象,也就是只查询一次数据库。
b) 此功能也被称为一级缓存,但实际开发中实用性很低。
2) 修改持久态对象的属性,可以自动同步到数据库对应的数据中。
a) 当修改了一个持久态对象的属性,后续又有操作而且提交了事务,则数据库自动调用更新操作,也一起修改。
b) 当登陆后,要求将当前系统时间,作为最后登陆时间保存到数据库中时,可以使用。
Session中get和load方法的区别?
1) 如果没有查询到数据,get会返回null,而load则直接提示错误。
2) 使用load查询时,可能会出现以下错误,因为load方式使用的是懒汉式加载方法。执行load方法时,不立刻查询数据库。当用到查询出的对象的属性时,才加载数据。游离态会报错
public void doRemove(Integer id) throws Exception {
// 注意,使用Hibernate删除时,必须先查询对象,再删除.
//HibernateSessionFactory.getSession().delete(findById(id));
String hql = "DELETE FROMNews AS n WHERE n.id = ?" ;
Query query = HibernateSessionFactory.getSession().createQuery(hql);
query.setInteger(0, id);
query.executeUpdate();
}
1) 当删除一条数据时,直接使用Session.delete(),因为简单。
2) 批量删除时,使用HQL形式。
public void doUpdate(News vo) throws Exception {
//HibernateSessionFactory.getSession().update(vo);
String hql = "UPDATE NewsAS 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的查询功能,也支持写SELECT,可以通过编写SELECT,来只查询对象中某一个或某几个属性。
public List testHQL()throws Exception {
String hql = "SELECTn.id,n.title FROM News AS n";
Query query = HibernateSessionFactory.getSession().createQuery(hql);
return query.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.idAS id,n.titleAS title FROM News ASn";
Query query = HibernateSessionFactory.getSession().createQuery(hql);
query
.setResultTransformer(newAliasToBeanResultTransformer(
News.class));
return query.list();
}Query有一个子接口是SQLQuery,该类支持SQL语句的处理,但实际开发中一般不用。
String sql = "SELECT id AS id,title AS title,content AScontent,pub_date AS pubDate FROM news";
SQLQuery query = HibernateSessionFactory.getSession().createSQLQuery(
sql);
query
.setResultTransformer(new AliasToBeanResultTransformer(
News.class));
return query.list();但,注意,在Oracle数据库中,为了提高性能,Oracle自动将所有字段名转换为大写,因此如果想要使用,必须将pojo对象的属性也写为大写才能设置。
Hibernate还可以将语句写到配置文件中。
<queryname="findAll">
FROM News AS n WHERE n.title LIKE ?
</ query >
通过程序读取配置文件,取得这段HQL,并生成Query对象,完成查询。
Query query =HibernateSessionFactory.getSession().getNamedQuery(
"findAll");
query.setString(0, "%测试%");
return query.list();Criteria也是Hibernate提供的一个查询对象,支持按对象的方式来完成查询
public List<News> testCriteria()throws Exception {
// 根据传入的pojo类型,查询该类型对应的全部数据
Criteria c = HibernateSessionFactory.getSession().createCriteria(
News.class);
// 1、WHERE id =26
//c.add(Restrictions.eq("id", 26));
// 2、WHERE id> 26
//c.add(Restrictions.gt("id", 26));
// 3、WHERE id< 26
// c.add(Restrictions.lt("id",26));
// 4、WHERE id>= 26
//c.add(Restrictions.ge("id", 26));
// 5、WHERE id<= 26
//c.add(Restrictions.le("id", 26));
// 6、WHERE id<> 26
//c.add(Restrictions.ne("id", 26));
// 7、WHEREtitle LIKE '%测试%'
// c.add(Restrictions.like("title","%测试%"));
// 8、WHERE idbetween 23 and 27
//c.add(Restrictions.between("id", 23, 27));
// 9、WHERE idIN (23,25,27)
// List<Integer> allIds= new ArrayList<Integer>();
// allIds.add(23);
// allIds.add(25);
// allIds.add(27);
//c.add(Restrictions.in("id", allIds));
// 10、复杂条件,需要使用and或or来连接各个条件
// WHERE id = 23 OR (id<> 26 AND title LIKE '%测试%')
c.add(Restrictions.or(Restrictions.eq("id", 23),Restrictions
.and(Restrictions.ne("id", 26),Restrictions.like(
"title","%测试%"))));
returnc.list();
}
如果想加入ORDER BY排序条件,需要使用Order对象。
c.addOrder(Order.desc("id"));
如果想加入统计函数和分组函数,则需要用到Projection这个类
ProjectionList pro =Projections.projectionList();
// 加入统计函数
pro.add(Projections.rowCount());
// 还可以加入分组条件
pro.add(Projections.groupProperty("title"));
c.setProjection(pro);