hibernate关联映射一对一主键
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了hibernate关联映射一对一主键相关的知识,希望对你有一定的参考价值。
从三个部分介绍Hibernate一对一主键关联映射。
1.基本介绍2.代码展示3.总结注意
1.基本介绍
一对一关联有两种情况:
单向一对一主键关联、双向一对一主键关联。
一对一主键关联:
是指两个表之间通过主键形成一对一的映射,例如,每个公民只允许拥有一个身份证,公民与身份证就是一对一的关系,
定义两张表,一张People表,一张IdCard表,People表的id既是该表的主键也是该表的外键,并且People的id也就是IdCard的id,
2.代码
单向一对一主键关联:people表的id既是主键,又是外键,所以在idcard表对应的实体类一方维护People的实例。
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="connection.driver_class">com.mysql.jdbc.Driver</property> <!-- 配置数据库连接字符串 --> <property name="connection.url"><![CDATA[jdbc:mysql://localhost:3306/test111?useUnicode=true&characterEncoding=utf8]]></property> <!-- 配置数据库连接用户名 --> <property name="connection.username">root</property> <!-- 配置数据库连接密码 --> <property name="connection.password">123456</property> <!-- 配置数据库方言 --> <property name="dialect">org.hibernate.dialect.MySQLDialect</property> <!-- 配置数据库表生成策略 --> <!--<property name="hibernate.hbm2ddl.auto">update</property> --> <!-- 配置是否打印显示SQL语句 --> <property name="show_sql">true</property> <!-- 配置是否格式化显示SQL语句 --> <property name="format_sql">true</property> <!-- 配置hibernate是否自动提交事务 --> <!--<property name="hibernate.connection.autocommit">true</property> --> <!-- 配置实体类对应的映射文件 --> <!-- 一对一双向主键关联 --> <mapping resource="com/great/entity2/People.hbm.xml"></mapping> <mapping resource="com/great/entity2/IdCard.hbm.xml"></mapping> <!-- 一对一单向主键关联 --> <mapping resource="com/great/entity3/People.hbm.xml"></mapping> <mapping resource="com/great/entity3/IdCard.hbm.xml"></mapping> </session-factory> </hibernate-configuration>
People.java
package com.great.entity3; public class People { // 一对一单向主键关联 private int id; private String pName; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getpName() { return pName; } public void setpName(String pName) { this.pName = pName; } }
IdCard.java
package com.great.entity3; public class IdCard { private int id; private String CardCode; private People people;//维护People public int getId() { return id; } public void setId(int id) { this.id = id; } public String getCardCode() { return CardCode; } public void setCardCode(String cardCode) { CardCode = cardCode; } public People getPeople() { return people; } public void setPeople(People people) { this.people = people; } }
People.hbm.xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd" > <hibernate-mapping package="com.great.entity2"> <!-- 配置实体类与数据库表的映射关系 --> <class name="com.great.entity3.People" table="people"> <!-- 配置主键映射关系 --> <id name="id" column="id" type="int"> <!-- 配置主键生成策略 --> <generator class="assigned"> </generator> </id> <!-- 配置属性和表字段映射关系 --> <property name="pName" column="pName" type="string"></property> </class> </hibernate-mapping>
IdCard.hbm.xml
<?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 package="com.great.entity3"> <class name="IdCard" table="idcard"> <id name="id" column="id" type="int"> <generator class="foreign"> <param name="property">people</param> </generator> </id> <!-- 配置属性和表字段映射关系 --> <property name="CardCode" column="CardCode" type="string"></property> <one-to-one class="com.great.entity3.People" name="people" cascade="all"></one-to-one> </class> </hibernate-mapping>
TestOneToOneUnidirectional.java//测试类
package com.great.test; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.Transaction; import org.hibernate.cfg.Configuration; import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.Test; import com.great.entity3.IdCard; import com.great.entity3.People; public class TestOneToOneUnidirectionalKeyRe { static Session session; // 一对一单向主键关联 @BeforeClass public static void setUpBeforeClass() throws Exception { // 加载hibernate主配置文件 Configuration cfg = new Configuration().configure(); // 构建session工厂 SessionFactory sf = cfg.buildSessionFactory(); // 打开session session = sf.openSession(); } @AfterClass public static void tearDownAfterClass() throws Exception { // 关闭session,释放资源 session.close(); } // 通过idcard查询people @Test public void testOneToOneSelect1() { IdCard idCard = (IdCard) session.get(IdCard.class, 1); System.out.println("身份证号码:" + idCard.getCardCode()); System.out.println("姓名:" + idCard.getPeople().getpName()); } // 通过保存idCard保存数据,只能通过向IdCard表中插入数据来保存数据 @Test public void testSave() { Transaction ts = session.beginTransaction(); IdCard idCard = new IdCard(); idCard.setCardCode("411487199505051234"); People people = new People(); people.setpName("陈大哥"); people.setId(2); idCard.setPeople(people); session.save(idCard); ts.commit(); } // 通过删除idCard删除数据 @Test public void testDelete() { IdCard idCard = (IdCard) session.get(IdCard.class, 2); Transaction ts = session.beginTransaction(); session.delete(idCard); ts.commit(); } }
双向一对一主键关联:在idcard表对应的实体类一方维护People的实例,同时在People表对应的实体类一方也维护idcard的实例。
新增部分用红色标注了,一个地方在People.hbm.xml中的配置,一处在People.java的属性。
IdCard.hbm.xml
<?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 package="com.great.entity2"> <class name="IdCard" table="idcard"> <id name="id" column="id" type="int"> <generator class="foreign"> <param name="property">people</param> </generator> </id> <!-- 配置属性和表字段映射关系 --> <property name="CardCode" column="CardCode" type="string"></property> <one-to-one class="com.great.entity2.People" name="people" cascade="all"></one-to-one> </class> </hibernate-mapping>
People.hbm.xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd" > <hibernate-mapping package="com.great.entity2"> <!-- 配置实体类与数据库表的映射关系 --> <class name="com.great.entity2.People" table="people"> <!-- 配置主键映射关系 --> <id name="id" column="id" type="int"> <!-- 配置主键生成策略 --> <generator class="assigned"> </generator> </id> <!-- 配置属性和表字段映射关系 --> <property name="pName" column="pName" type="string"></property>
<!-- 新增 -->
<one-to-one name="idCard" class="com.great.entity2.IdCard" cascade="all"></one-to-one> </class> </hibernate-mapping>
IdCard.java
package com.great.entity2; public class IdCard { private int id; private String CardCode; private People people; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getCardCode() { return CardCode; } public void setCardCode(String cardCode) { CardCode = cardCode; } public People getPeople() { return people; } public void setPeople(People people) { this.people = people; } }
People.java
package com.great.entity2; public class People { // 一对一主键关联 private int id; private String pName; private IdCard idCard;//新增 public int getId() { return id; } public void setId(int id) { this.id = id; } public String getpName() { return pName; } public void setpName(String pName) { this.pName = pName; } public IdCard getIdCard() { return idCard; } public void setIdCard(IdCard idCard) { this.idCard = idCard; } }
TestOneToOneBoth.java
package com.great.test; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.Transaction; import org.hibernate.cfg.Configuration; import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.Test; import com.great.entity2.IdCard; import com.great.entity2.People; public class TestOneToOneBothKeyRe { static Session session; // 一对一双向主键关联 @BeforeClass public static void setUpBeforeClass() throws Exception { // 加载hibernate主配置文件 Configuration cfg = new Configuration().configure(); // 构建session工厂 SessionFactory sf = cfg.buildSessionFactory(); // 打开session session = sf.openSession(); } @AfterClass public static void tearDownAfterClass() throws Exception { // 关闭session,释放资源 session.close(); } // 通过people查询idcard @Test public void testOneToOneSelect1() { IdCard idCard = (IdCard) session.get(IdCard.class, 1); System.out.println("身份证号码:" + idCard.getCardCode()); System.out.println("姓名:" + idCard.getPeople().getpName()); } // 通过idcard查询people @Test public void testOneToOneSelect2() { IdCard idCard = (IdCard) session.get(IdCard.class, 1); System.out.println("身份证号码:" + idCard.getCardCode()); System.out.println("姓名:" + idCard.getPeople().getpName()); } // 插入数据 @Test public void testSave() { Transaction ts = session.beginTransaction(); // 设置idcard IdCard idCard = new IdCard(); idCard.setCardCode("411487199505051234"); // 设置people People people = new People(); people.setpName("格格"); people.setId(2); // 互相保存 idCard.setPeople(people); people.setIdCard(idCard); // 保存idcard,必须保存idCard,保存People出错,Hibernate这次首先持久化了people对象, // 由于people表中的id字段建立了外键关系,故持久化失败. session.save(idCard); ts.commit(); } // 通过删除idCard删除数据 @Test public void testDelete() { IdCard idCard = (IdCard) session.get(IdCard.class, 2); Transaction ts = session.beginTransaction(); session.delete(idCard); ts.commit(); } }
3.注意:
1.配置cascade="all",它可以保证主控方所关联的被控方的操作一致性,例如,主控方进行save、update或delete操作时,被控方会进行同样的操作。
2.单向一对一关联时,select、save、update、delete,只能操作idCard。
2.双向一对一关联时,查询可以进行两个方向查询【因为互相维护对方的实例】,但是save、update、delete,只能操作idCard,例如session.save(idCard);
以上是关于hibernate关联映射一对一主键的主要内容,如果未能解决你的问题,请参考以下文章
Hibernate之关联关系映射(一对一主键映射和一对一外键映射)
Hibernate,关系映射的多对一单向关联多对一双向关联一对一主键关联一对一外键关联多对多关系关联
Hibernate学习———— hibernate一对一关系映射详解