前言:本文适合对hibernate有一定了解的人,未了解hibernate的读者可能会有点困难。众所周知,hibernate是个十分强大的ORM框架,然而越强大的东西规则就越多,hibernate也是,hibernate用得好那就是如虎添翼,用的不好会严重拖累系统性能,还不如直接用java的JDBC编程。我的博客主要写的是我在学习hibernate的过程中学习到的优化建议方法。将持续改进和更新。有一本畅销书《精通hibernate:java持久化对象技术详解》,写的非常好,本文章是个人的读书笔记。
一.基础优化建议
1.id一般都是用Long型。
2.包装类优先:由于在数据库中存在许多null值,在插入数据的时候也会有如果有某字段没有赋值就会默认为空,既然数据库支持,那hibernate也应该支持,所以一般在使用hibernate传参入到数据库的时候都使用包装类,因为包装类允许null值。典型的例如:session.get(Cunstom.class,new Long(1)),除此之外,类里面的属性定义都应该是用包装类类定义,比如使用Integer price;而不是int price。
3.访问类属性策略:在
<property name=”name” column=”NAME” access=”field”/>
中配置access=”field”之后,hibernate就会直接访问该实例的name属性,而不是调用该方法。( 需要注意的是,hibernate是通过反射访问属性的,所以不论变量的修饰符是public还是private,hibernate都能访问)。access的另一个值是property,默认值,一般不用配置,表示hibernate通过市里的setXXX和GetXXX来访问属性。
4.派生属性:
<property name=”totalPrice” formula=”(select sum(0.price) from ORDERS o where o.CUSTEMER_ID=ID)”/>
在查询customer对象时,select语句会包含以上用于计算派生属性的子查询语句:
select ID,NAME,SEX,`CUSTOMER DESCRIPTION`,( select sum(0.price) from ORDERS o where o.CUSTEMER_ID=1) from CUSTOMERS。
(ps:上面这个“`CUSTOMER DESCRIPTION` “符号是引用标示符,如果字段名中包含空格或者特殊字符那么就需要使用这个引用标示符)
5.property的映射属性:
insert属性:如果为false表示该字段永远不能被插入,默认为true;
update属性:如果为false表示该字段永远不能被更新,默认为true;
class的映射属性:
dynamic-insert属性:如果为true,表示每当保存一个对象时,会动态生成insert语句,insert语句仅包含所有取值不为null的字段,默认值false.
dynamic-update 属性:如果为true,表示每当更新一个对象时,会动态生成update语句,在update语句中仅包含所有取值需要更新的字段。
Tip:一般建议把dynamic-insert属性和dynamic-update 属性设置为true,这样可以节省数据库sql查询时的系统开销。
6.比较对象是否相等:
先看如下代码:
Customer c1=new Customer(“Tom”); Customer c2=new Customer(“Tome”); Cusomer c3=c1;
如果打印”c1==c2”或者”c1.equals(c2)”结果都是false,这样应该是不对的,他俩应该是相等的,所以我们建议在类中重写equals方法以方便比较两个对象是否相等。如下:
public Boolean equals(Object o){ if(this == o) return true; if(!(o instanceof CustomerId)) return false; final CustomerId other = (CustomerId) o; if(!this.getName.equals(other.getName()) return false; if(!companyId.equals(other.getCompanyId())) return false; return true; }
7.hibernate用OID来区分对象,该OID实际是关系映射文件中的id项,如下:
<id name=”MemoId” type=”Long” column=”ID”> <generator class=”increament”/> </id>
8.hibernate的标示符生成器:
increament (常用): 由hibernate 自动以递增的方式生产标识符,每次增量为1;
identity:由数据库底层生产标识符;
sequence:由底层的序列来生产标识符,注意少数数据库可能不支持,例如mysql;
hilo:hibernate根据high/low算法来生成标识符;
native: 根据底层数据库对自动生成标识符的支持能力,来选择identity,sequence,hilo;
uuid.hex: hibernate采用128位UUID来生成算法标识符,UUID能够在网络环境中生成唯一的字符串标识符,但占用太多空间,一般不推荐;
assigned:自然主键,由java生成。一般不推荐;
foreign:用另一个关联的对象的标识符来作为当前对象的标识符,主要适用于一对一关联的场合。
二.hibernate的映射:一对多关联关系