07hibernate_one2one_ufk_1
hibernate一对一唯一外键关联映射(单向关联Person---->IdCard)
一对唯一外键关联映射是多对一关联映射的特例:
public class Person {
private int id;
private String name;
private IdCard idCard; //在多的一方加入一个外键,数据库中增加一个字锻
-------------------------------------------------------------------------
<hibernate-mapping>
<class name="com.bjsxt.hibernate.Person" table="t_person">
<id name="id">
<generator class="native"/>
</id>
<property name="name"/>
<many-to-one name="idCard" unique="true"/>
</class>
</hibernate-mapping>
-------------------------------------------------------------------------
可以采用<many-to-one>标签,指定多的一端的unique=true,这样就限制了多的一端的多重性为一
通过这种手段映射一对一唯一外键关联
-------------------------------------------------------------------------
导出表语句:
create table t_idcard (id integer not null auto_increment, cardNo varchar(255), primary key (id))
create table t_person (id integer not null auto_increment, name varchar(255), idCard integer unique, primary key (id))
alter table t_person add index FK785BED80539D4B66 (idCard), add constraint FK785BED80539D4B66 foreign key (idCard) references t_idcard (id)
-------------------------------------------------------------------------
mysql> use 07hibernate_one2one_ufk_1;
Database changed
mysql> desc t_person;
+--------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| name | varchar(255) | YES | | NULL | |
| idCard | int(11) | YES | UNI | NULL | |
+--------+--------------+------+-----+---------+----------------+
3 rows in set (0.00 sec)
mysql> desc t_idcard;
+--------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| cardNo | varchar(255) | YES | | NULL | |
+--------+--------------+------+-----+---------+----------------+
2 rows in set (0.00 sec)
TestSave1:由于没有设置cascade="all",或者你只保存了多方,没有保存一方,则会抛出异常信息:org.hibernate.TransientObjectException
org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: com.bjsxt.hibernate.IdCard
TestSave1:
Hibernate: insert into t_idcard (cardNo) values (?)
Hibernate: insert into t_person (name, idCard) values (?, ?)
mysql> select * FROM t_person;
+----+------+--------+
| id | name | idCard |
+----+------+--------+
| 2 | 菜10 | 1 |
+----+------+--------+
1 row in set (0.00 sec)
mysql> select * FROM t_idcard;
+----+----------------+
| id | cardNo |
+----+----------------+
| 1 | 88888888888888 |
+----+----------------+
1 row in set (0.00 sec)
TestLoad:
Hibernate: select person0_.id as id1_0_, person0_.name as name1_0_, person0_.idCard as idCard1_0_ from t_person person0_ where person0_.id=?
person.name=菜10
Hibernate: select idcard0_.id as id0_0_, idcard0_.cardNo as cardNo0_0_ from t_idcard idcard0_ where idcard0_.id=?
idCard.cardNo=88888888888888
------------------------------------------------------
package com.bjsxt.hibernate;
import org.hibernate.Session;
import junit.framework.TestCase;
public class One2OneTest extends TestCase {
public void testSave1() {
Session session = null;
try {
session = HibernateUtils.getSession();
session.beginTransaction();
IdCard idCard = new IdCard();
idCard.setCardNo("88888888888888");
Person person = new Person();
person.setName("猪八戒");
person.setIdCard(idCard);
//不能成功保存,因为IdCard是Transient状态
session.save(person);
session.getTransaction().commit();
}catch(Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}finally {
HibernateUtils.closeSession(session);
}
}
public void testSave2() {
Session session = null;
try {
session = HibernateUtils.getSession();
session.beginTransaction();
IdCard idCard = new IdCard();
idCard.setCardNo("88888888888888");
一对唯一外键关联映射是多对一关联映射的特例:
public class Person {
private int id;
private String name;
private IdCard idCard; //在多的一方加入一个外键,数据库中增加一个字锻
-------------------------------------------------------------------------
<hibernate-mapping>
<class name="com.bjsxt.hibernate.Person" table="t_person">
<id name="id">
<generator class="native"/>
</id>
<property name="name"/>
<many-to-one name="idCard" unique="true"/>
</class>
</hibernate-mapping>
-------------------------------------------------------------------------
可以采用<many-to-one>标签,指定多的一端的unique=true,这样就限制了多的一端的多重性为一
通过这种手段映射一对一唯一外键关联
-------------------------------------------------------------------------
导出表语句:
create table t_idcard (id integer not null auto_increment, cardNo varchar(255), primary key (id))
create table t_person (id integer not null auto_increment, name varchar(255), idCard integer unique, primary key (id))
alter table t_person add index FK785BED80539D4B66 (idCard), add constraint FK785BED80539D4B66 foreign key (idCard) references t_idcard (id)
-------------------------------------------------------------------------
mysql> use 07hibernate_one2one_ufk_1;
Database changed
mysql> desc t_person;
+--------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| name | varchar(255) | YES | | NULL | |
| idCard | int(11) | YES | UNI | NULL | |
+--------+--------------+------+-----+---------+----------------+
3 rows in set (0.00 sec)
mysql> desc t_idcard;
+--------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| cardNo | varchar(255) | YES | | NULL | |
+--------+--------------+------+-----+---------+----------------+
2 rows in set (0.00 sec)
TestSave1:由于没有设置cascade="all",或者你只保存了多方,没有保存一方,则会抛出异常信息:org.hibernate.TransientObjectException
org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: com.bjsxt.hibernate.IdCard
TestSave1:
Hibernate: insert into t_idcard (cardNo) values (?)
Hibernate: insert into t_person (name, idCard) values (?, ?)
mysql> select * FROM t_person;
+----+------+--------+
| id | name | idCard |
+----+------+--------+
| 2 | 菜10 | 1 |
+----+------+--------+
1 row in set (0.00 sec)
mysql> select * FROM t_idcard;
+----+----------------+
| id | cardNo |
+----+----------------+
| 1 | 88888888888888 |
+----+----------------+
1 row in set (0.00 sec)
TestLoad:
Hibernate: select person0_.id as id1_0_, person0_.name as name1_0_, person0_.idCard as idCard1_0_ from t_person person0_ where person0_.id=?
person.name=菜10
Hibernate: select idcard0_.id as id0_0_, idcard0_.cardNo as cardNo0_0_ from t_idcard idcard0_ where idcard0_.id=?
idCard.cardNo=88888888888888
------------------------------------------------------
package com.bjsxt.hibernate;
import org.hibernate.Session;
import junit.framework.TestCase;
public class One2OneTest extends TestCase {
public void testSave1() {
Session session = null;
try {
session = HibernateUtils.getSession();
session.beginTransaction();
IdCard idCard = new IdCard();
idCard.setCardNo("88888888888888");
Person person = new Person();
person.setName("猪八戒");
person.setIdCard(idCard);
//不能成功保存,因为IdCard是Transient状态
session.save(person);
session.getTransaction().commit();
}catch(Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}finally {
HibernateUtils.closeSession(session);
}
}
public void testSave2() {
Session session = null;
try {
session = HibernateUtils.getSession();
session.beginTransaction();
IdCard idCard = new IdCard();
idCard.setCardNo("88888888888888");
//先保存一方,再保存多方,OK!
session.save(idCard);
Person person = new Person();
person.setName("菜10");
person.setIdCard(idCard);
session.save(person);
session.getTransaction().commit();
}catch(Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}finally {
HibernateUtils.closeSession(session);
}
}
public void testLoad1() {
Session session = null;
try {
session = HibernateUtils.getSession();
session.beginTransaction();
//由于 testSave1()抛出异常,所以数据库中的记录id=2
Person person = (Person)session.load(Person.class, 2);
System.out.println("person.name=" + person.getName());
System.out.println("idCard.cardNo=" + person.getIdCard().getCardNo());
session.getTransaction().commit();
}catch(Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}finally {
HibernateUtils.closeSession(session);
}
}
}
session.save(idCard);
Person person = new Person();
person.setName("菜10");
person.setIdCard(idCard);
session.save(person);
session.getTransaction().commit();
}catch(Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}finally {
HibernateUtils.closeSession(session);
}
}
public void testLoad1() {
Session session = null;
try {
session = HibernateUtils.getSession();
session.beginTransaction();
//由于 testSave1()抛出异常,所以数据库中的记录id=2
Person person = (Person)session.load(Person.class, 2);
System.out.println("person.name=" + person.getName());
System.out.println("idCard.cardNo=" + person.getIdCard().getCardNo());
session.getTransaction().commit();
}catch(Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}finally {
HibernateUtils.closeSession(session);
}
}
}