Hibernate关联映射1:一对一主键关联

来源:互联网 发布:linux tar指令 编辑:程序博客网 时间:2024/06/01 22:47

2张表之间通过主键形成一对一映射关系,如一个人只能有一张身份证:

t_identity_card表建表语句:

CREATE TABLE `t_identity_card` (  `id` int(11) NOT NULL,  `identity` int(11) NOT NULL,  PRIMARY KEY (`id`)) ENGINE=InnoDB DEFAULT CHARSET=gb2312;

t_person表建表语句:

CREATE TABLE `t_person` (  `id` int(11) NOT NULL,  `name` varchar(255) NOT NULL,  `age` int(11) NOT NULL,  PRIMARY KEY (`id`),  CONSTRAINT `FK_ID` FOREIGN KEY (`id`) REFERENCES `t_identity_card` (`id`)) ENGINE=InnoDB DEFAULT CHARSET=gb2312;

hibernate.cfg.xml:

<?xml version='1.0' encoding='utf-8'?><!DOCTYPE hibernate-configuration PUBLIC"-//Hibernate/Hibernate Configuration DTD 3.0//EN""http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd"><hibernate-configuration><session-factory><property name="dialect">org.hibernate.dialect.MySQLDialect</property><property name="connection.driver_class">com.mysql.jdbc.Driver</property><property name="connection.url">jdbc:mysql://localhost:3306/mydb</property><property name="connection.username">root</property><property name="connection.password">196428</property><property name="hibernate.show_sql">true</property><mapping resource="com/po/IdentityCard.hbm.xml" /><mapping resource="com/po/Person.hbm.xml" /></session-factory></hibernate-configuration>

单向一对一主键关联:

t_identity_card表:

public class IdentityCard implements Serializable {private static final long serialVersionUID = 1L;private int id;private int identity;private Person person;public int getId() {return id;}public void setId(int id) {this.id = id;}public int getIdentity() {return identity;}public void setIdentity(int identity) {this.identity = identity;}public Person getPerson() {return person;}public void setPerson(Person person) {this.person = person;}}

由于t_identity_card表使用foreign主键生成策略,故在t_identity_card表的配置文件中必须配置主键生成表t_person,这样在向t_identity_card表中插入数据时才能找到所需的主键值,所以单向一对一主键关联中只有t_person<-t_identity_card,没有t_person->t_identity_card

<?xml version="1.0"?><!DOCTYPE hibernate-mapping PUBLIC    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"    "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd" ><hibernate-mapping>    <class name="com.po.IdentityCard" table="t_identity_card">    <id name="id" column="id" type="integer"><generator class="foreign"><param name="property">person</param></generator></id>        <property name="identity" column="identity" type="integer"/>        <one-to-one name="person" class="com.po.Person"/>    </class></hibernate-mapping>

t_person表:

public class Person implements Serializable {private static final long serialVersionUID = 1L;private int id;private String name;private int age;public int getId() {return id;}public void setId(int id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}}
<?xml version="1.0"?><!DOCTYPE hibernate-mapping PUBLIC"-//Hibernate/Hibernate Mapping DTD 3.0//EN""http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd" ><hibernate-mapping>    <class name="com.po.Person" table="t_person"><id name="id" column="id" type="integer"><generator class="assigned"/></id><property name="name" column="name" type="string"/>        <property name="age" column="age" type="integer"/>    </class></hibernate-mapping>

测试一下:

public class Test {public static void main(String[] args) {Configuration conf = new Configuration();SessionFactory sessionFactory = conf.configure().buildSessionFactory();Session session = sessionFactory.openSession();IdentityCard identityCard = new IdentityCard();identityCard.setIdentity(123456);Person person = new Person();person.setId(1);person.setName("sean");person.setAge(25);identityCard.setPerson(person);Transaction tran = session.beginTransaction();session.save(identityCard);tran.commit();IdentityCard identityCard2 = (IdentityCard)session.get(IdentityCard.class, 1);Person person2 = identityCard2.getPerson();System.out.println(person2.getName());session.close();}}

测试结果为:

Hibernate: insert into t_identity_card (identity, id) values (?, ?)sean

只向t_identity_card表中插入了数据,t_person表为空,由于没有设置关联关系的cascade属性,在持久化一张表的时候,并不会级联的持久化另一张表

将t_identity_card表的映射文件中的关联关系修改为:<one-to-one name="person" class="com.po.Person"cascade="all" />

Hibernate: select person_.id, person_.name as name1_, person_.age as age1_ from t_person person_ where person_.id=?Hibernate: insert into t_identity_card (identity, id) values (?, ?)Hibernate: insert into t_person (name, age, id) values (?, ?, ?)sean

双向一对一主键关联:

这时需要对t_person表的配置做一些修改:

public class Person implements Serializable {private static final long serialVersionUID = 1L;private int id;private String name;private int age;private IdentityCard identityCard;//新增public int getId() {return id;}public void setId(int id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}public IdentityCard getIdentityCard() {return identityCard;}public void setIdentityCard(IdentityCard identityCard) {this.identityCard = identityCard;}}
<?xml version="1.0"?><!DOCTYPE hibernate-mapping PUBLIC"-//Hibernate/Hibernate Mapping DTD 3.0//EN""http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd" ><hibernate-mapping>    <class name="com.po.Person" table="t_person"><id name="id" column="id" type="integer"><generator class="native"/></id><property name="name" column="name" type="string"/>        <property name="age" column="age" type="integer"/>    <!--新增-->    <one-to-one name="identityCard" class="com.po.IdentityCard" cascade="all" />    </class></hibernate-mapping>

测试一下:

public class Test {public static void main(String[] args) {Configuration conf = new Configuration();SessionFactory sessionFactory = conf.configure().buildSessionFactory();Session session = sessionFactory.openSession();IdentityCard identityCard = new IdentityCard();identityCard.setIdentity(123456);Person person = new Person();person.setId(1);person.setName("sean");person.setAge(25);identityCard.setPerson(person);person.setIdentityCard(identityCard);Transaction tran = session.beginTransaction();session.save(identityCard);tran.commit();Person person_tmp = (Person)session.get(Person.class, 1);IdentityCard id_card_tmp = person_tmp.getIdentityCard();System.out.println(id_card_tmp.getIdentity());id_card_tmp = (IdentityCard)session.get(IdentityCard.class, 1);person_tmp = id_card_tmp.getPerson();System.out.println(person_tmp.getName());session.close();}}

测试结果为:

Hibernate: select person_.id, person_.name as name1_, person_.age as age1_ from t_person person_ where person_.id=?Hibernate: insert into t_identity_card (identity, id) values (?, ?)Hibernate: insert into t_person (name, age, id) values (?, ?, ?)123456sean

Hibernate首先持久化了identityCard对象,将测试代码中的session.save(identityCard)修改为session.save(person),再次测试:

Hibernate: insert into t_person (name, age, id) values (?, ?, ?)Exception in thread "main" org.hibernate.exception.ConstraintViolationException: Could not execute JDBC batch update......Caused by: java.sql.BatchUpdateException: Cannot add or update a child row:a foreign key constraint fails (`mydb`.`t_person`, CONSTRAINT `FK_ID` FOREIGN KEY (`id`) REFERENCES `t_identity_card` (`id`))......

Hibernate这次首先持久化了person对象,由于t_person表中的id字段建立了外键关系,故持久化失败,删除掉t_person表中id字段的外键关系之后,插入正常:

Hibernate: insert into t_person (name, age, id) values (?, ?, ?)Hibernate: insert into t_identity_card (identity, id) values (?, ?)123456sean

可见Hibernate有时不是很智能,save的对象将会首先被持久化,这时要特别注意表上建立的关联关系

0 0
原创粉丝点击