想想也是,以前做项目时用Hibernate的确比较乱,有时图个方便随处调用它的API,到后期往往导致那种难以察觉的持久化小Bug产生,再花大时间大精力去跟踪,去调试。
既然有了这个机会,咱也好好研究研究文档,系统地做个整理。
把对象持久化
fritz.setColor(Color.GINGER);
fritz.setSex('M');
fritz.setName("Fritz");
Long generatedId = (Long) sess.save(fritz);
在这里,把对象持久化对于ID有2种方式:第一是,自动生成的ID,当调用save()成功后,会自动产生ID,当然要数据库支持。第二是,我们自己在save()方法调用之前就去赋值给ID,也可以用save()的一个重载方法,sess.save( fritz, new Long(1234) ); 这都是我们手动创建ID的方法。一般我们不会采用第二种方法。
遗留问题:如果要持久化的对象中关联了其他对象,会出现什么问题
从数据库载入对象
从ID取出记录
if (cat==null) {
cat = new Cat();
sess.save(cat, id);
}
return cat;
这个没什么好说的,一般我们都要get()方法来得到一个对象,很少用load(),关键就在于当没有记录时,get()返回null,而load()会报错。
还有一点要提的就是refresh()方法。往往有些时候,我们从数据库取出一个对象的时候,不能保证在save()之前,数据库没有被”骚扰过“,这也是在实际中比较难以察觉的微小同步化问题,如果遇到问题,可以试着refresh(),保证拿到的是最新的资料。
sess.flush(); //force the SQL INSERT
sess.refresh(cat); //re-read the state (after the trigger executes)
通过查询取出记录
"from Cat as cat where cat.birthdate < ?")
.setDate(0, date)
.list();
List kittens = session.createQuery(
"from Cat as cat where cat.mother = ?")
.setEntity(0, pk)
.list();
Cat mother
= (Cat) session.createQuery("select cat.mother from Cat as cat where cat = ?")
.setEntity(0, izi)
.uniqueResult();
Query mothersWithKittens
= (Cat) session.createQuery("select mother from Cat as mother left join fetch mother.kittens");
Set uniqueMothers = new HashSet(mothersWithKittens.list());
一般,我们都要尽量硬编码SQL语句,即使使用类似这样的语句 "from Cat as cat where cat.birthdate < ”+today ,其实这些对于数据库来说都是硬编码,如果有1000条这样的查询语句,数据库就要编译1000次,而使用?这种形式,数据库往往只是编译一次,其中意思明白即可
在很多情况下,我们知道了ID可以直接取出一个对象,不知道ID,通过查询就会搜出一个List来,这时Hibernate给我们了一个 uniqueResult()方法调用,直接取出一个对象
也有些情况,比如外连接,我们会搜索出很多重复的值,当然是我们自己认为的重复值,可以配合Set来做到唯一性。
上面的查询都是基本的HQL,在业务中用于很简单的需求,比较 getAll getById 或者 getByName getByDate等等。
那么如果涉及排序,涉及多种查询条件,比如大于,小于,模糊查询等等穿插在一起的复杂查询,我们一般使用Criteria Queries。
首先我们需要了解一个重要的接口:
Criterion
下面这些类都实现了这个接口
- AbstractEmptinessExpression, BetweenExpression, EmptyExpression, Example, IdentifierEqExpression, IlikeExpression, InExpression, Junction, LikeExpression, LogicalExpression, NaturalIdentifier, NotEmptyExpression, NotExpression, NotNullExpression, NullExpression, PropertyExpression, SimpleExpression, SizeExpression, SQLCriterion, SubqueryExpression
其中有BetweenExpression,IlikeExpression, InExpression等等(这些都可以从字面意思来理解)
这些类要通过一个静态工厂来创建,它就是Restrictions ,它可以用来创建上面这些类
上面这些接口啦,类啦,都是在
org.hibernate.criterion
这个大名鼎鼎的包里,里面还有Order 等有用的类 我们在理解这些类和接口的时候都把它们当作纯SQL里的关键字好了,没有什么深奥的
好了,我们来随便搞个例子吧
现在我们定义这样一个类 产品好了 Product
public class Product {
private Long id;
private String name;
private Provider provider;
private Date createDate;
}
id ,产品名字,以及一个供应商类
public class Provider {
private Long id;
private String name;
}
很好理解吧。
现在我们来模拟这样一个查询 搜索
1产品名类似 “螺帽”
2 产品的创建日期在今天之前的
3要以创建日子倒排序
4产品里的供应商的名字要类似 “化工” 的
5在搜索出来后,我们只取8条记录
.add(Restrictions.le("createDate", new Date()))
.addOrder((Order.desc("createDate")))
.createCriteria("provider").add(Restrictions.like("name", "%化工%"))
.setMaxResults(8).list()
想想当年,我们在做ASP开发的时候,许多SQL的复杂组合的assemble方法都要自己来写,现在真是方便了很多
还有一个关键的类,不得不提一下,对那种架构级要求较高的项目非常有用
DetachedCriteria
Some applications need to create criteria queries in "detached mode", where the Hibernate session is not available. This class may be instantiated anywhere, and then a
大致意思是,我们可以设计一些许多复杂查询的类,这些类都是不和session也就是与hibernate、数据库完全脱钩的一些查询,当我们要使用的时候,只要执行