1、对象关系映射
1-1、单向多对一关联
产品和分类的关系:多个不同产品属于同一种分类。
private Category category;
<many-to-one name="category" column="categoryId" not-null="true" />
1-2、一对多映射
private Set products = new HashSet();
<set name="products" <!--Category 中集合属性名称为 products-->
table="product" <!--集合属性对应表的名称为 product-->
schema="test" <!--表的 schema 名称为 test-->
lazy="true" <!--此集合采用延时加载策略-->
inverse="true" <!--由关联属性的另一方作为关联的主控方-->
cascade="delete" <!--采用级联删除,当 Category 被删除时关联的此集合内容也将被删除-->
sort="natural" <!--自然排序集合内容-->
order-by="productId asc" <!--按 productId 字段升序排列集合内容-->
>
<key column="category_fk" />
<one-to-many class="petstore.domain.Product" />
</set>
1-3、继承映射
2、Hibernate 操作对象
2-1、对象的三种状态
● 瞬时态(Transient)--VO(Value Ojbect)
对象实例产生到被 JVM 垃圾回收为止并不受 Hibernate 框架管理。
● 持久态(Persistent)--PO(Persistent Ojbect)
对象实例被 Hibernate 框架管理,该对象可能是刚被保存的,或刚从数据库中被加载的。Hibernate 会检测处于持久态的对象任何改动,在当前操作单元执行完毕将对象与数据库同步,即将对象的属性保存到数据库映射对应的字段中。简单点说就是该实体对象与 session 发生关系,而且处于 session 的有效期内。
● 托管态(Detached)--VO(Value Ojbect)
与持久对象关联的 Session 被关闭后,对象就变为托管的,可继续被修改。托管对象如果重新关联到某个新的 Session 上,会再次变为持久的,同时改动也将会被持久化到数据库。这个期间的转变过程可以看作是应用程序事务,即中间会给用户思考时间的长时间运行的操作单元。
处于托管态对象具有与数据库表记录间的联系(持久化标识,identifier)。
2-2、对象操作的应用程序接口
● 修改对象
对于已经持久化的对象,不需要调用某个特定的方法就可以实现修改持久化,因为 Hibernate 会自动调用 flush() 方法保证与数据库的同步。
对于处于托管状态的实例,Hibernate 通过提供 Session.update() 或 Session.merge() 方法,重新关联托管实例。但是需要注意的是:如果具有持久化标识(identifier)的对象之前已经被另一个会话连接(secondSession)装载了,应用程序关联操作会发生异常。
使用 merge() 方法时,用户不必考虑 session 的状态,可随时将修改保存到数据库中。例如:Session 中存在相同标识的持久化实例时,Hibernate 便会根据用户给出的对象状态覆盖原有的持久化实例的状态。
另外,Hibernate 还提供了 saveOrUpdate()方法,它即可分配新持久化标识(identifier),保存瞬时(transient)对象,又可更新/重新关联托管的(identifier)实例。
● 删除对象
通过 HQL 语句,调用重载的 delete(),可以一次删除多个对象。
session.delete("from Customer as c where c.customerId <3");
● 查询对象
已知对象表示符值查询
对象标识符未知查询 HQL
根据某些特定条件查询 QBC,Query By Criteria
按详例查询 QBE,Query By Example
调用数据库查询 native SQL
查询条件参数 ? 查询条件参数索引,由 0 开始。
查询条件实名 :name
外置命名查询
在映射文件定义查询语句,将程序与查询语句分离:
<query name="CategoryById"
<! [CDATA[
from Category c where c.categoryId>? ]]>
</query>
程序调用:
Query q = sess.getNamedQuery("CategoryById");
q.setLong(0, name);
List cats = q.List();
用 Query 提供的 iterate() 方法遍历查询结果,如果查询的结果在 session 或二级缓存(second-level cache)中,那么使用 iterate() 方法可以得到更好的性能。
如果 JDBC 驱动支持可滚动的 ResuleSet,Query 接口可以使用 ScrollableResults,允许你在查询结果中灵活移动(需要保持数据库连接和游标 cursor 处于抑制打开状态)。
ScrollableResults cates = q.scroll();
cates.first()
cates.scroll(5);
● cascade 和 inverse 级联操作
inverse
只对 set,one-to-many(或 many-to-many)有效,对于 many-to-one,one-to-one 无效
对集合起整体作用
cascade
对关系标记都有效
对集合的一个元素起作用,如果集合为空,那么 cascade 不会引发关联操作
作用时机:在 flush 时(commit 会自动执行 flush),hibernate 会自行判断每个 set 是否有变化,对有变化的 set 执行相应的 SQL,if (inverse) return。即:cascade 在前,inverse 在后。
异常:
org.hibernate.exception.ConstraintViolationException: could not insert
原因是 category_fk 字段约束不能为空,而在新建的 Product 对象时插入了空值,而且关联关系由 Caterogy 对象维持,而被关联的 Product 对象不知道自己与哪个 Category 对象关联。说到底就是 pro 对象的 categoryId 值为空。
posted on 2009-04-11 20:46
黄小二 阅读(414)
评论(0) 编辑 收藏 所属分类:
S/S2SH 、
J2EE 、
J2SE