一对一主键双向联系关系(在数据库层控制级联删除)

一对一主键双向关联(在数据库层控制级联删除)

--数据库oracle

在数据库设计里,one-to-one模型可以用2种方法来实现。
1,主键关联:这时候要保证2个表的主键具有完全相同的值。
2,外键关联:其中一个表使用外键关联另一个表。

模型:person vs idcard (人:身份证)

--这是带主外键关联的两张表。
-- 删除表
DROP TABLE idcard ;
DROP TABLE person ;

-- 创建表
CREATE TABLE person
(
 id VARCHAR2(32) PRIMARY KEY ,
 name VARCHAR2(20) NOT NULL ,
 age NUMBER
) ;
CREATE TABLE idcard
(
 id VARCHAR2(32) REFERENCES person(id) ON DELETE CASCADE,
 serial VARCHAR2(18) NOT NULL ,
 expiry NUMBER
) ;

2、pojo类
public class Person {
 private String id ;//perosn的id
 private String name;//名字
 private int  age;   //年龄
 
 private IdCard idcard;
}

public class IdCard {
 private String id;//卡号
 private String serial;//卡的号码
 private int expiry;//可以使用年限
}

3、添加和删除的测试类。
public class PersonIdCardOperation {
 private Session session = null;

 public PersonIdCardOperation() {
  this.session = new Configuration().configure().buildSessionFactory()
    .openSession();
 }

 // 先插入一个用户
 public void insert(Person per) {
  this.session.save(per);
  this.session.beginTransaction().commit();
  session.close();
 } 
 public void delete(String id)
 {
  String hql = "DELETE FROM Person WHERE id=?" ;
  Query q = this.session.createQuery(hql) ;
  q.setString(0, id) ;
  q.executeUpdate() ;
  this.session.beginTransaction().commit() ;
 }

 /**
  * @param args
  */
 public static void main(String[] args) {
  PersonIdCardOperation po = new PersonIdCardOperation();
  Person per = new Person() ;
  per.setName("jack");
  per.setAge(25);

//         准备好一张身份证
  IdCard ic = new IdCard();
  ic.setSerial("888888888888888");
  ic.setExpiry(12);
  
  
  per.setIdcard(ic);
  ic.setPerson(per);

//  po.insert(per) ;
  po.delete("ff8080812887f59c012887f59d080001");
 }

}

4、person配置文件
<hibernate-mapping>
 <class name="org.onetoone.com.Person" table="person">
  <id name="id" type="java.lang.String">
   <column name="id" length="32" />
   <generator class="uuid.hex"></generator>
  </id>
  <property name="name" type="java.lang.String">
   <column name="name" length="20" not-null="true" />
  </property>
  <property name="age" type="java.lang.Integer">
   <column name="age" />
  </property>
  <!-- 下面中的cascade="all",级联保存person对象关联的idcard对象。-->
 
  <one-to-one name="idcard"
   class="org.onetoone.com.IdCard"
   cascade="all"
   outer-join="true" >
  </one-to-one>
 </class>
</hibernate-mapping>
5、idCard配置文件
<hibernate-mapping>
 <class name="org.onetoone.com.IdCard" table="idcard">
 <!-- 引用Person的主键作为idCard的主键和外键 -->
  <id name="id" column="id" type="java.lang.String">
   <generator class="foreign">
    <param name="property">person</param>
   </generator>
  </id>

  <one-to-one name="person"
   class="org.onetoone.com.Person" 
   constrained="true">
  </one-to-one>

  <property name="serial" type="java.lang.String">
   <column name="serial" length="18" not-null="true" />
  </property>
  <property name="expiry" type="java.lang.Integer">
   <column name="expiry" not-null="true" />
  </property>
 </class>
</hibernate-mapping>

6、总结一些属性的用法。
   person配置文件中的一些属性:
   1、class="uuid.hex" 用uuid.hex会自动生成的一个32位值。
   2、cascade="all" 解释一下cascade的用法:
      all :所有情况下均进行关联操作,all 的意思是save-update + delete 。
      none:所有情况下均不进行关联操作。这是默认值。
      save-update:在执行save/update/saveOrUpdate时进行关联操作。
      delete:在执行delete时进行关联操作。
 
      all-delete-orphan 的意思是当对象图中产生孤儿节点时,在数据库中删除该节点

      all比较好理解,举个例子说一下all-delete-orphan:
      Category与Item是一对多的关系,也就是说Category类中有个Set类型的变量items.
      举个例子,现items中存两个Item, item1,item2,如果定义关系为all-delete-orphan
     当items中删除掉一个item(比如用remove()方法删除item1),那么被删除的Item类实例
      将变成孤儿节点,当执行category.update(),或session.flush()时
      hibernate同步缓存和数据库,会把数据库中item1对应的记录删掉
   3、outer-join="true":解释一下outer-join的用法:
            outer-join参数允许下列三个不同值:
            auto:(默认) 使用外连接抓取关联(对象),如果被关联的对象没有代理(proxy)
            true:一直使用外连接来抓取关联
            false:永远不使用外连接来抓取关联 
   4、因为是双向关联,所以每个配置文件里面都要配<one-to-one>的关联关系

   idCard配置文件中的一些属性:
   constrained="true":解释一下constrained的用法。(这个属性的说明是个难点吧)
   1、constrained的默认值是false。
   2、级联删除我是在数据库层设置的。这里的constrained就没有什么用了。
   3、要是不在数据库中控制级联删除。设个属性还是有用的。
  
   hibernate中constrained主要是在one-to-one的foreign主键生成策略的映射中使用。手册上说:
  constrained(约束) (可选) 表明该类对应的表对应的数据库表,和被关联的对象所对应的数据库表之间,通过一个外键引用对 

 主键进行约束。这个选项影响save()和delete()在级联执行时的先后顺序以及 决定该关联能否被委托(也在schema export tool 

中被使用).
  如果constrained=true,则表明存在外键与关联表对应,并且关联表中肯定存在对应的键与其对应。hibernate生成的sql将使用

  inner join. 另外该选项最关键的是影响save和delete的先后顺序。例如增加的时候,如果constainted=true,则会先增加关联 

表,然后增加本表。删除的时候反之


7、本程序的级联删除是在数据库层控制的。