随笔-7  评论-24  文章-102  trackbacks-0


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 黄小二 阅读(415) 评论(0)  编辑  收藏 所属分类: S/S2SHJ2EEJ2SE

只有注册用户登录后才能发表评论。


网站导航: