专注于互联网--专注于架构

最新标签
网站地图
文章索引
Rss订阅

首页 »Java教程 » hibernate映射:Hibernate的映射关联关系 »正文

hibernate映射:Hibernate的映射关联关系

来源: 发布时间:星期四, 2009年1月15日 浏览:60次 评论:0
  Hibernate映射关联关系和我们现实世界里事物关联关系样.比如在UML语言中,以客户Customer和订单Order关系为例.个客户可以发送多个订单,而个订单只能属于个客户,这是对多关联,因此可以成为单向关联.如果同时包含了两两种关联关系,就成为双向关联.在关系数据库中只有外键参照主键关系.所以关系数据库实际上至支持,或对多单向关系.在类于类的间关系中.要算多对关系和数据库中外键参照主键关系最匹配了.因此如果使用单向关联从订单到客户多对单向关联,在订单类中就要定义个客户属性.表示这个订单属于哪个客户,而客户类就无需定义存放订单集合属性了.下面写个简单例子.

  //首先定义客户类
  public Customer implements Sreializable {
  private Long id;
  private String name;
  //省略属性访问思路方法
  }
  //然后定义订单类
  public Order implements Sreializable {
  private Long id;
  private String orderName;
  private Customer customer;
  //省略属性访问思路方法,要注意是Customer访问思路方法.
  }
  Customer类所有属性和CUSTOMERS表所有属性对应,创建起来就比较简单了.下面主要看下Order类映射文件.
  <property name="orderName" type="">
  <column name="ORDER_NAME" length="15"/>
  </property>


  customer属性是是Customer类型,而ORDERS表CUSTOMER_ID是整数类型,是不匹配.所以我们不能用普通<property>元素来定义,而我们需要使用<many-to-one>元素来配置了.

  <many-to-one name="customer" column="CUSTOMER_ID" ="包名.Customer" not-null="true"/>

  <many-to-one>元素负责建立Order订单类customer属性和数据库中CUSTOMER_ID外键字段的间映射.

  name:设定映射文件属性名

  column:设定和持久化类对应外键名

  :设定持久化类属性类型,这里指定具体类,也就是主键存在

  not-null:设定为true表示customer属性不允许为null,默认是false,这个属性会影响到bhm2ddl工具,会为ORDERS表CUSTOMER_ID外键设置为不允许空约束,但是不会影响到hbm2java工具生长java源代码.此外还会影响到Hibernate运行时行为,在保存Order对象时候会检查customer属性是否为null.用hbm2ddl编译的后得到数据库文件如下:

  create table CUSTOMERS (
  ID big not null,
  NAME varchar(15),
  primary key (ID)
  );
  create table ORDERS (
  ID big not null,
  ORDER_NUMBER varchar(15),
  CUSTOMER_ID big not null,
  primary key (ID)
  );
  alter table ORDERS add index FK8B7256E516B4891C (CUSTOMER_ID),
  add constra FK8B7256E516B4891C foreign key (CUSTOMER_ID) references CUSTOMERS (ID);


  看到结果我们可以简单把<many-to-one>理解为在数据库中,创建外键作用.上边这个例子就简单演示了Hibernate映射关联关系,至于对多关联关系比这个稍微复杂点.而且可以看出,当Hibernate持久化个临时对象时候,在默认情况下它不会自动持久化关联其他临时对象,而是会抛出TransientObjectException异常.如果希望Hibernate持久化对象时候也自动持久化说关联对象,就要把<many-to-one>元素cascade属性设置为save-update,表示级联操作意思,cascade属性默认值为none.当这个属性设置OK了.数据库就实现了级联保存更新操作.

  在类和类的间建好了关联关系的后,就可以方便个对象得到它关联对象.例如Customer customer=order.getCustomer;这样获得了Customer对象了.但是如果想获得所有属于Customer客户Order订单对象,就涉及到了对多双向关联了.在内存中,从个对象导航都另个对象要比从数据库中通过个字段查询另个字段快多,但是也给编程时候带来了麻烦,随意修改个对象就可能牵发而动全身,所以说双向关联比较复杂,但是类和类的间到底建立单向还是双向关联,这个要根据业务需求来决定.比如说业务需求根据指定客户查询客户所有订单,根据指定订单,查询出发这个订单客户.这个时候我们不妨用多对双向关联处理.其实上边例子映射文件已经简历了客户和订单的间对多双向关联关系,只不过要在客户类中加个集合属性: [Page]

  private orders = HashSet;
  public getOrders {
   orders;
  }
  public void Orders(Set orders) {
  this.orders = orders;
  }


  有了orders属性,客户就可以通过getOrders思路方法或者客户全部订单了,Hibernate在定义这个集合属性时候必须声明为接口类型,但是不光光是Set还有Map和List,这样可以提高强壮性,就是说思路方法接受对象只要是实现了Set接口就OK.避免出现null值现象.这里要注意是hbm2java工具生成类集合属性代码时,不会给它个集合对象例子,这里我们需要自己手动修改,当然不修改也是可以.接下来还要在customer.hbm.xml映射文件里映射集合类型orders属性,当然这个和order表<many-to-one>同理,所以不能通过普通<property>元素来设置属性和字段映射关系.要使用<>元素来设置:

  < name="orders" cascade="save-update">
  <key column="CUSTOMER_ID">
  <one-to-many ="包名.Order">
  </>


  name:设定类属性名

  cascade:设置为save-update表示级联保存更新,当保存或更新Customer类时候会级联保存更新跟它关联Order类.

  <key>元素是用来设定跟持久化类关联外键

  <one-to-many>元素看起来很熟悉,哦是设置外键元素反过来了.这里它是用来设置所关联持久化类.这里设置为和客户关联订单Order类,这里表明这个属性里要存放组Order类型对象.

  这个<>元素是表示orders属性声明为类型.

  <>元素还有个inverse属性,这个思路方法主要是在给已存在数据库中字段建立关联时候很有用.就是说当我们获得数据库中两个表两条记录对象customer客户对象和order订单对象(映射文件已经建立了他们类和类的间关联,但外键值为null情况下)然后我们想建立这个客户对象和订单对象的间关联,我们要先order.Customer(customer);然后在customer.getOrder.add(order);在Hibernate自动清理缓存Cache持久化对象时候会提交两条SQL语句.进行了两个update操作.但是实际上只修改了条记录.重复执行SQL语句是会降低系统运行效率,当把inverse属性设置为true时候,同样操作就会合并到条SQL语句执行了,inverse默认为false;

  级联删除就很简单了,把cascade属性设置为delete,如果你删除了个客户,就会先执行删除这个客户全部订单SQL语句,然后在删除这个客户,所谓删除个持久化对象不是在内存中删除这个对象,而是删除数据库中相关记录,这个对象依然在内存中,只不过由持久化状态转为临时状态,当这个对象引用消失后,这个对象会被垃圾回收.但是如果我又想级联删除,还想级联保存,更新时候应该如何办呢?这个时候我们将cascade属性设置为all-delete-orphan就OK了.非常简单明了.我们还可以通过持久化类customer.getOrder.rumove(order);解除关联.这里操作表示获得客户订单集合对象,然后从集合对象中删除order订单,其实这种操作意义不大,当我们不需要这个订单时候完全可以删除它,解除关联的后如果设置了级联删除属性,这个无用记录也是要被删除.其实解除关联就是把外键设为null.通常我们外键都要约束不可以为空.

  映射关联还有种多对多关联,是种自身关联关系.就是同张表.自己和自己关联.比如说张人表,地球人是人,美国人,中国人,日本人都属于地球人,中国人有分北京人,山东人.日本人也有下比如东京人.下面设想如果日本人被消灭掉了,那么东京人也应该都被没有了吧,这就是种关系,自身对自身关联关系.这就有点类似树结构了.下面用个例子演示这种关系,代码来源于孙MM<<精通Hibernate>>书.

  public Category implements Serializable {
  private Long id;
  private String name;
  private Category parentCategory;
  private Set childCategories; [Page]
  public Category(String name, mypack.Category parentCategory, Set childCategories) {
    this.name = name;
    this.parentCategory = parentCategory;
    this.childCategories = childCategories;
  }
  public Category {
  }
  public Category(Set childCategories) {
    this.childCategories = childCategories;
  }
  public Category getParentCategory {
     this.parentCategory;
  }
  public void ParentCategory(Category parentCategory) {
    this.parentCategory = parentCategory;
  }
  public Set getChildCategories {
     this.childCategories;
  }
  public void ChildCategories(Set childCategories) {
    this.childCategories = childCategories;
  }
  //为了节省空间省略了id,name属性访问思路方法
  }
  <hibernate-mapping >
  < name="mypack.Category" table="CATEGORIES" >
  <id name="id" type="long" column="ID">
   <generator ="increment"/>
  </id>
  <property name="name" type="" >
    <column name="NAME" length="15" />
  </property>
  <
    name="childCategories"
  cascade="save-update"
    inverse="true"
    >
    <key column="CATEGORY_ID" />
    <one-to-many ="mypack.Category" />
   </>
  <many-to-one
    name="parentCategory"
    column="CATEGORY_ID"
    ="mypack.Category"
    />
  </>
  </hibernate-mapping>
   我觉得这种方式其实和上边对多,关系样,只不过两个用都是同个类罢了.看下例子理解上应该很简单

0

相关文章

读者评论

发表评论

  • 昵称:
  • 内容: