【SSH快速进阶】——Hibernate一对一映射(one-to-one)——主键关联映射
2015-12-10 16:50
615 查看
现实生活中,有很多场景需要用到一对一映射,比如每个学生只有一个学生证,每个公民只有一张身份证等。这里用公民-身份证来举例说明。
![](https://oscdn.geek-share.com/Uploads/Images/Content/201911/12/6e931cb288d4cb9f3d699fc8e8d26a05)
在Hibernate中实现一对一映射,有两种实现方式:1、主键关联;2、唯一外键关联,这里先说一下主键关联映射。
主键关联映射:其中一个表的主键依赖于另一张表的主键而建立起的一对一的关系,这两张互相关联的表的主键一致。
关联映射又可细分为单向关联映射和双向关联映射。
一对一单向关联映射
一对一单向关联映射,即一个对象依赖另一个对象,比如根据人能找到他的身份证:
![](https://oscdn.geek-share.com/Uploads/Images/Content/201911/12/49942595385d221f3dd5a0f197a05403)
Po对象:
IdCard .java
Person.java
映射文件:
IdCard.hbm.xml
Person.hbm.xml
上述配置文件中
运行程序,实际执行的sql语句如下,除了创建两张表,还为t_person表创建了约束:
插入测试:
测试中,先定义idCard,person.setIdCard(idCard)之后,直接保存person,虽然session没有直接save(idCard),但是由于一对一主键关联映射的特性,必须先保存关联对象idCard,才可以保存person。所以在执行session.save(person)时,先保存的是idCard。
可以发现执行的sql语句为:
查询测试
实际执行的sql语句:
执行结果
一对一双向关联映射
一对一双向关联映射,即两个对象互相依赖,根据人也能找到他的身份证,根据某人的身份证也能找到这个人:
![](https://oscdn.geek-share.com/Uploads/Images/Content/201911/12/bab5653d87d0158a55624cddd96b6a98)
在上面的一对一单向关联映射中,根据Person可以查到IdCard,但只根据IdCard不能查询到Person,要想根据IdCard也能查询到Person,IdCard的po和配置文件也可以这么写:
IdCard.java
IdCard.hbm.xml
这里标签不能加constrained=”true”的原因是:如果加上后,t_person主键既依赖于t_idCard的主键,t_idCard的主键也依赖于t_person的主键,您想想,是不是就“死循环”了?
这样在查询IdCard时,就可以顺便查出person
执行结果:
查询执行的sql语句:
但是标签只影响查询,并不影响保存。比如执行下列保存时:
只会保存idCard,而不会保存person。
【 转载请注明出处——胡玉洋《【SSH快速进阶】——Hibernate一对一映射(one-to-one)——主键关联映射》】
在Hibernate中实现一对一映射,有两种实现方式:1、主键关联;2、唯一外键关联,这里先说一下主键关联映射。
主键关联映射:其中一个表的主键依赖于另一张表的主键而建立起的一对一的关系,这两张互相关联的表的主键一致。
关联映射又可细分为单向关联映射和双向关联映射。
一对一单向关联映射
一对一单向关联映射,即一个对象依赖另一个对象,比如根据人能找到他的身份证:
Po对象:
IdCard .java
public class IdCard { private int id; private String cardNo; //getter、setter }
Person.java
public class Person { private int id; private String name; private IdCard idCard; //getter、setter }
映射文件:
IdCard.hbm.xml
<hibernate-mapping package="org.hibernate.test" > <class name="com.danny.hibernate.IdCard" table="t_idCard"> <id name="id"> <generator class="native"/> </id> <property name="cardNo"/> </class> </hibernate-mapping>
Person.hbm.xml
<hibernate-mapping package="org.hibernate.test" > <class name="com.danny.hibernate.Person" table="t_person"> <id name="id" type="int"> <generator class="foreign"> <param name="property">idCard</param> </generator> </id> <one-to-one name="idCard" constrained="true"/> <property name="name"/> </class> </hibernate-mapping>
上述配置文件中
<one-to-one name="idCard" constrained="true"/>是配置一对一关联的核心,表示一个Person对应一个IdCard。constrained=”true”表示t_person表的主键上同时有个外键指向被关联的表(t_idCard)的主键,会对表t_person创建约束,约束t_person的id只能跟idCard的主键一样。
运行程序,实际执行的sql语句如下,除了创建两张表,还为t_person表创建了约束:
alter table t_person drop foreign key FK785BED803EEB3F3E drop table if exists t_idCard drop table if exists t_person create table t_idCard (id integer not null auto_increment, cardNo varchar(255), primary key (id)) create table t_person (id integer not null, name varchar(255), primary key (id)) alter table t_person add index FK785BED803EEB3F3E (id), add constraint FK785BED803EEB3F3E foreign key (id) references t_idCard (id)
插入测试:
session.beginTransaction(); IdCard idCard=new IdCard(); idCard.setCardNo("123456789"); Person person=new Person(); person.setName("danny"); person.setIdCard(idCard); session.save(person); session.getTransaction().commit();
测试中,先定义idCard,person.setIdCard(idCard)之后,直接保存person,虽然session没有直接save(idCard),但是由于一对一主键关联映射的特性,必须先保存关联对象idCard,才可以保存person。所以在执行session.save(person)时,先保存的是idCard。
可以发现执行的sql语句为:
insert into t_idCard (cardNo) values (?) insert into t_person (name, id) values (?, ?)
查询测试
Person person=(Person)session.load(Person.class, 1); System.out.println("person的name:"+person.getName()); System.out.println("person的cardNo:"+person.getIdCard().getCardNo());
实际执行的sql语句:
select person0_.id as id0_0_, person0_.name as name0_0_ from t_person person0_ where person0_.id=? select idcard0_.id as id1_0_, idcard0_.cardNo as cardNo1_0_ from t_idCard idcard0_ where idcard0_.id=?
执行结果
person的name:danny person的cardNo:123456789
一对一双向关联映射
一对一双向关联映射,即两个对象互相依赖,根据人也能找到他的身份证,根据某人的身份证也能找到这个人:
在上面的一对一单向关联映射中,根据Person可以查到IdCard,但只根据IdCard不能查询到Person,要想根据IdCard也能查询到Person,IdCard的po和配置文件也可以这么写:
IdCard.java
public class IdCard { private int id; private String cardNo; private Person person; }
IdCard.hbm.xml
<hibernate-mapping package="org.hibernate.test" > <class name="com.danny.hibernate.IdCard" table="t_idCard"> <id name="id"> <generator class="native"/> </id> <property name="cardNo"/> <one-to-one name="person" fetch="join"/><!-- fetch值为select时,可以实现懒加载 --> </class> </hibernate-mapping>
这里标签不能加constrained=”true”的原因是:如果加上后,t_person主键既依赖于t_idCard的主键,t_idCard的主键也依赖于t_person的主键,您想想,是不是就“死循环”了?
这样在查询IdCard时,就可以顺便查出person
IdCard idCard=(IdCard)session.load(IdCard.class, 1); System.out.println("person的cardNo:"+idCard.getCardNo()); System.out.println("person的name:"+idCard.getPerson().getName());
执行结果:
person的cardNo:123456789 person的name:danny
查询执行的sql语句:
select idcard0_.id as id1_0_, idcard0_.cardNo as cardNo1_0_ from t_idCard idcard0_ where idcard0_.id=? Hibernate: select person0_.id as id0_0_, person0_.name as name0_0_ from t_person person0_ where person0_.id=?
但是标签只影响查询,并不影响保存。比如执行下列保存时:
session.beginTransaction(); Person person=new Person(); person.setName("danny"); IdCard idCard=new IdCard(); idCard.setCardNo("123456789"); idCard.setPerson(person); session.getTransaction().commit();
只会保存idCard,而不会保存person。
【 转载请注明出处——胡玉洋《【SSH快速进阶】——Hibernate一对一映射(one-to-one)——主键关联映射》】
相关文章推荐
- Linux Generating SSH Keys
- perl脚本实现限制ssh最大登录次数(支持白名单)
- rsync ssh 数据同步分析
- Hibernate Oracle sequence的使用技巧
- jsp Hibernate批量更新和批量删除处理代码
- jsp hibernate的分页代码第1/3页
- 搭建SSH时的思考和遇到的几个问题的解决方法
- SSH 使用原理 与解释
- JAVA+Hibernate 无限级分类
- SSH整合中 hibernate托管给Spring得到SessionFactory
- jsp hibernate 数据保存操作的原理
- hibernate中的增删改查实现代码
- 解决hibernate+mysql写入数据库乱码
- java优化hibernate性能的几点建议
- java Hibernate延迟加载
- hibernate 常用方法介绍
- Linux VPS利用SSH重置ROOT密码的方法
- ssh,scp自动登陆的实现方法
- ssh非交互式密码授权远程执行脚本