现在的位置: 首页 > 综合 > 正文

Hibernate关键点整理

2018年05月21日 ⁄ 综合 ⁄ 共 3839字 ⁄ 字号 评论关闭
又是一个新项目开始了,老大发话,写个Hibernate的技术纲要,便于开发过程中规范。

想想也是,以前做项目时用Hibernate的确比较乱,有时图个方便随处调用它的API,到后期往往导致那种难以察觉的持久化小Bug产生,再花大时间大精力去跟踪,去调试。

既然有了这个机会,咱也好好研究研究文档,系统地做个整理。

把对象持久化

DomesticCat fritz = new DomesticCat();
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取出记录

Cat cat = (Cat) sess.get(Cat.class, id);
if (cat==null{
cat 
= new Cat();
sess.save(cat, id);
}

return cat;

这个没什么好说的,一般我们都要get()方法来得到一个对象,很少用load(),关键就在于当没有记录时,get()返回null,而load()会报错。

还有一点要提的就是refresh()方法。往往有些时候,我们从数据库取出一个对象的时候,不能保证在save()之前,数据库没有被”骚扰过“,这也是在实际中比较难以察觉的微小同步化问题,如果遇到问题,可以试着refresh(),保证拿到的是最新的资料。

sess.save(cat);
sess.flush(); 
//force the SQL INSERT
sess.refresh(cat); //re-read the state (after the trigger executes)

通过查询取出记录

List cats = session.createQuery(
"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条记录

session.createCriteria(Product.class).add(Restrictions.like("name""%螺帽%"))
                        .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

Criteria may be obtained by passing a session to

getExecutableCriteria() . All methods have the same semantics and behavior as the corresponding methods of the

Criteria interface.

大致意思是,我们可以设计一些许多复杂查询的类,这些类都是不和session也就是与hibernate、数据库完全脱钩的一些查询,当我们要使用的时候,只要执行

getExecutableCriteria()把session传递进去就可以了。通过这个类,我们可以构建出一个很底层的查询层,提供各式各样的复杂查询,上层代码只要拥有一个session就可以来调用它们,而它们与上层是完全没有耦合的。话说回来,这样做,开发速度会比较慢,但对于后期维护来讲,可以一个一劳永逸大快人心的设计模式。

抱歉!评论已关闭.