码迷,mamicode.com
首页 > Web开发 > 详细

Hibernate ORM(2):Hibernate使用记录之一

时间:2015-11-05 20:39:33      阅读:304      评论:0      收藏:0      [点我收藏+]

标签:

#1 ORM文件中,<property>元素的access属性可以指定待持久化类属性的访问方式

1         <property name="userName" type="string" access="property">
2 
3             <column name="USER_NAME" length="20" not-null="true" />
4 
5         </property>
  • property为缺省访问方式,则hibernate通过setter和getter访问属性。因此如果一个字段仅在ORM文件有定义、在java类中并无定义,java类只要提供其setter/getter后,hibernate仍旧可以读取这个值。

 

1         <property name="createdBy" type="string" access="field">
2 
3             <column name="CREATED_BY" length="20" not-null="true" />
4 
5         </property>
  • 如果某个属性没有setter/getter,或者access设置为field,则hibernate用过反射直接访问属性;

 

#2 动态映射字段

<property name=”totalPrice” formula=”SELECT SUM(o.price) FROM orders o WHERE o.customer_id=id” />
  • Hibernate将根据formula的sql语句动态为totalPrice设置值,formula可以操作各表字段,所以并不需要orders表中有total_price的字段;如果formula查询的结果为空则totalPrice的值返回null,因此Java类中totalPrice的属性需要设置为Double包装类型。

 

#3 动态生成INSERT和UPDATE语句

缺省情况下Hibernate会预先生成并编译针对所有column的insert和update子句;但预编译好的sql语句不管待写入DB的字段是否为空,也不管待写入DB的字段是否有更新,都全部进行操作,当column比较多的时候缺省设置会耗费比较多的DB资源;

因此Hibernate一并提供关键字用于控制column的插入和更新:

1 <property name=”price” insert=”false” />
  • 缺省为true;如果为false,表示Hibernate不再为insert生成price字段,也就是该DB column不能被插入;

 

1 <property name=”price” update=”false” />
  • 缺省为true;如果为false,表示Hibernate不再为update生成price字段,也就是该DB column不能被更新;

 

1 <class name=”org.hibernate.totorial.domain.User” table=”USER” mutable=”false” />
  • 缺省为true;如果为false,表示所有该class的property的update属性为false,该实例不能被更新;

 

1 <class name=”org.hibernate.totorial.domain.User” table=”USER” dynamic-insert=”true” />
  • 缺省为false;如果为true,表示插入一个对象时动态生成insert语句,insert的字段仅包含取值不为null的字段;

 

1 <class name=”org.hibernate.totorial.domain.User” table=”USER” dynamic-update=”true” />
  • 缺省为false;如果为true,表示更新一个对象时动态生成update语句,update的字段仅包含取值有更新的字段;

 

#4 java.sql.Date & java.util.Date & java.sql.Time & java.sql.Timestamp的区别

Java.util.Date的时间格式为:yyyy/mm/dd/ : hh/mm/ss

Java.sql.Date的时间格式为:yyyy/mm/dd

Java.sql.time的时间格式为:hh/mm/ss

Java.sql.Timestamp的时间格式为:yyyy/mm/dd/ : hh/mm/ss/ns

Java.util.Calender深入封装了java.util.Date,并且功能更全面

 

#5 数据库表主键ID的设置

设计数据库表的时候主键ID一般使用非业务相关的独立字段,从而保证主键在任何时候都不受业务变动的影响;

 1 <hibernate-mapping>
 2 
 3 <class name="org.hibernate.tutorial.domain.Cart" table="CARTS" dynamic-update="true">
 4 
 5         <id name="cartID" type="int" access="field">
 6 
 7             <column name="CART_ID" />
 8 
 9             <generator class="increment" />
10 
11         </id>
12 
13 </class>
14 
15 </hibernate-mapping>

 

常用的主键ID生成器如下:

  • 代理主键Increment:

由Hibernate设置,适用于所有数据库;

如果多个SessionFactory同时连接一个DB,则increment的自增操作失效;

仅适合DB被单个Hibernate App访问的场景;

OID必须为Long、INT或者Short;

  • 代理主键Identity:

由DB设置,根据不同DB配置不同的DB dialect,从而映射成不同的类型,MySQL为auto_increment,SQL Server为identity;

底层数据库必须支持自动增长字段的类型;

OID必须为Long、INT或者Short;

  • 代理主键Sequence:

由Hibernate设置,但序列来自于底层数据库;

底层数据库必须支持序列,MySQL不支持序列,Oracle,DB2和PostgreSQL支持;

OID必须为Long、INT或者Short;

  • 单自然主键assigned:

表示由应用程序为当前赋值,并且该属性为自然主键,业务相关,永远不会为null;

一般而言saveOrUpdate()方法通过判断主键ID是否为null来确定对象的状态,当主键的生成属性generator为assigned的时候则不能判断;只能通过额外的属性<version>来控制;如果unsaved-value为null就表示为临时对象,非null就表示游离对象;

 1 <hibernate-mapping>
 2 
 3 <class name="org.hibernate.tutorial.domain.Cart" table="CARTS"
 4 
 5 dynamic-update="true">
 6 
 7         <id name="name" type="string" access="field">
 8 
 9             <column name="CART_NAME" />
10 
11             <generator class="assigned" />
12 
13         </id>
14 
15         <version name="version" column="VERSION" unsaved-value="null"/>
16 
17     </class>
18 
19 </hibernate-mapping>

 

  • 复合自然主键composite-id:
 1 <hibernate-mapping>
 2 
 3        <class name="mypack.Customer" table="CUSTOMERS">
 4 
 5               <composite-id name="customerId" class="mypack.CustomerId">
 6 
 7                      <key-property name="name" column="NAME" type="string" />
 8 
 9                      <key-property name="company" column ="COMPANY_ID" type="long" />
10 
11               </composite-id>
12 
13               <version name="version" column="VERSION" unsaved-value="null" />
14 
15               <many-to-one name="company" column="CLIENT_ID"
16 
17 insert="false” update="false”
18 
19                      class="org.hibernate.tutorial.domain.Company" />
20 
21        </class>
22 
23 </hibernate-mapping>

Customer对象由CustomerId对象确定,CustomerId由name和company组成;

凡是由自然键担任主键的class都需要定义version属性以区分状态;

<many-to-one>标签表示company与customer为多对一的关系;

Insert和update属性为false表示当customer对象被保存的时候,会忽略company属性;

 

#6 多对一单向关联关系

  • 如果将IN_ORDER和WINE设计为多对一的单向关联关系,则IN_ORDER类中需要定义一个WINE属性,WINE类中则无须定义IN_ORDER的set集合属性;
  • IN_ORDER的映射文件中需要定义<many-to-one>标签,在类中则对应Wine类型的类属性
 1 <many-to-one name="wine"
 2 
 3                      column="WINE_ID"
 4 
 5                      class="org.hibernate.tutorial.domain.Wines"
 6 
 7                      not-null="true"
 8 
 9                      cascade="save-update"
10 
11                      lazy="true" />

name对应java类中的属性名;

column对应db表中的外键名;

class对应关联属性的类型;

not-null缺省为false,如果为true表示增加关联属性的约束检查,保存IN_ORDER对象时会检查WINE是否为null,如果此时WINE还没有持久化则抛出异常;

cascade缺省为none,表示不进行级联更新;如果为save-update则在更新IN_ORDER对象的同时会级联更新WINE对象;

lazy缺省为proxy,表示对WINE对象使用延迟检索策略并使用代理;如果为false则在加载IN_ORDER对象的同时就会检索并加载WINE对象;

 

  • 由于是多对一的单向关联,则WINE的映射文件中无须定义<set>标签;
  • 当Hibernate持久化一个临时对象(IN_ORDER)时,缺省情况下并不会自动持久化其关联的临时对象(WINE),因此会报错;可以通过<many-to-one>标签的cascade=”save-update”属性解决,表示当IN_ORDER进行insert或者update操作时,会优先对关联对象WINE执行insert或者update;

 

#7 多对一双向关联关系

  • 类与类之间设计成是单向关联还是双向关联,这是由具体业务决定;如果将IN_ORDER和WINE设计为多对一的双向关联关系,则IN_ORDER类中需要定义一个WINE属性,WINE类中需要定义IN_ORDER的set集合属性;
  • IN_ORDER的映射文件中需要定义<many-to-one>标签,同上
 1 <many-to-one name="wine"
 2 
 3                      column="WINE_ID"
 4 
 5                      class="org.hibernate.tutorial.domain.Wines"
 6 
 7                      not-null="true"
 8 
 9                      cascade="save-update"
10 
11                      lazy="true" />

 

  • WINE的映射文件中需要定义<set>标签,在类中则对应Set<InOrder>类型的类属性
1 <set name="inOrders" inverse="true" cascade="save-update">
2 
3                      <key column="IN_ORDER_ID" />
4 
5                      <one-to-many class="org.hibernate.tutorial.domain.InOrders" />
6 
7 </set>

name对应java类中的属性名;

inverse 优化Hibernate性能;

cascade表示是否对inOrders属性执行级联策略,取值为none(缺省值), save-update(级联保存和更新), delete(级联删除), all-delete-orphan(级联删除解除关联的对象)

<key>对应级联属性的外键;

<one-to-many>对应级联属性的类型;

 

  • 首先分别持久化两个不相关的WINE和IN_ORDER,然后在他们之间建立关联,需要在java代码中执行如下代码,
wine.getInOrders().add(inOrder);

inOrder.setWine(wine);

 

  • Hibernate一旦检测到内存中类属性的变动(wine的inOrders属性,inOrder的wine属性)则会独立执行sql语句,因此会执行两条sql语句;但实际效果仅仅是更新IN_ORDER表的WINE_ID列,为了解决这个性能问题,Hibernate引入inverse=”true”属性,仅执行wine一方的属性变动;

 

  • 在建立两个对象的双向关联时,应该同时修改关联两端的对象的属性,以保证程序的健壮性;同样,解除关联也必须是双方同时解除;

Hibernate ORM(2):Hibernate使用记录之一

标签:

原文地址:http://www.cnblogs.com/leo-chen-2014/p/4940569.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!