Hibernate 一对一外键单向关联
事实上,单向1-1与N-1的实质是相同的,1-1是N-1的特例,单向1-1与N-1的映射配置也非常相似。只需要将原来的many-to-one元素增加unique="true"属性,用于表示N的一端也必须是唯一的,在N的一端增加了唯一的约束,即成为单向1-1。基于外键的单向1-1的配置将与无连接表N-1关联的many-to-one增加unique="true"属性即可。
one-to-one 不会加载字段,它告诉HIBERNATE 怎样加载其引用对象.如何加载呢,默认根据 主键加载其引用对象.如在t_person 中查到id=2,自动加载t_idCard 中id=2的对象信息. constrained="true",表明person主键是个外键,表示当前主键上存在着idCard约束,当 前主键id作为外键,参照了idCard.
大家都知道hibernate中的one-to-one映射主要有两种策略,(1)一对一主键关联(单向和双向)。(2)一对一外键映射(单项和双向)。本文主要讲解一下,一对一外键映射中的双向问题,在此前先通过一个实例了解。
person和idCard,是一种一对一的关系,其中
t_person表
id name idCard(unique)
1 张三
2 王五 1
其中王五是没有idcard,这也符合现实中的,有些人是没有身份证的。
t_idCard表
id cardNo
1 11111111111111
实体类:
IdCard
package com.bjpowernode.hibernate;
public class IdCard {
private int id;
private String cardNo;
private Person person;
public Person getPerson() {
return person;
}
public void setPerson(Person person) {
this.person = person;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getCardNo() {
return cardNo;
}
public void setCardNo(String cardNo) {
this.cardNo = cardNo;
}
}
Person
package com.bjpowernode.hibernate;
public class Person {
private int id;
private String name;
private IdCard idCard;
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 IdCard getIdCard() {
return idCard;
}
public void setIdCard(IdCard idCard) {
this.idCard = idCard;
}
}
(3)配置文件
IdCard的:
<?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.bjpowernode.hibernate">
<class name="IdCard" table="t_idCard">
<id name="id">
<generator class="native"/>
</id>
<property name="cardNo"/>
<one-to-one name="person" class="Person" />
</class>
</hibernate-mapping>
Person的:
<?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.bjpowernode.hibernate">
<class name="Person" table="t_person">
<id name="id">
<generator class="native"/>
</id>
<property name="name"/>
<many-to-one name="idCard" cascade="all"class="IdCard"
unique="true" column="card_ID" />
</class>
</hibernate-mapping>
(3)
向t_person中插入数据:
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();
Person person = new Person();
person.setName("张三");
session.save(person);
session.getTransaction().commit();
}catch(Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}finally {
HibernateUtils.closeSession(session);
}
}
结果如下:
mysql> select * from t_person;
+----+------+---------+
| id | name | card_ID |
+----+------+---------+
| 1 | 张三 | NULL |
+----+------+---------+
1 row in set (0.00 sec)
mysql> select * from t_idcard;
Empty set (0.00 sec)
在插入数据:
public void testSave2() {
Session session = null;
try {
session = HibernateUtils.getSession();
session.beginTransaction();
IdCard idCard = new IdCard();
idCard.setCardNo("1111111111");
session.save(idCard);
Person person = new Person();
person.setName("王五");
//建立关联
person.setIdCard(idCard);
session.save(person);
session.getTransaction().commit();
}catch(Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}finally {
HibernateUtils.closeSession(session);
}
}
数据库中的结果如下:
mysql> select * from t_person;
+----+------+---------+
| id | name | card_ID |
+----+------+---------+
| 1 | 张三 | NULL |
| 2 | 王五 | 1 |
+----+------+---------+
2 rows in set (0.00 sec)
mysql> select * from t_idcard;
+----+------------+
| id | cardNo |
+----+------------+
| 1 | 1111111111 |
+----+------------+
1 row in set (0.00 sec)
(4)加载数据,这样的话就可以从person的一端加载到idCard,
如下:
public void testLoad1() {
Session session = null;
try {
session = HibernateUtils.getSession();
session.beginTransaction();
Person person = (Person)session.load(Person.class, 2);
System.out.println("person.name=" + person.getName());
System.out.println("person.cardNo="+ person.getIdCard().getCardNo());
session.getTransaction().commit();
}catch(Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}finally {
HibernateUtils.closeSession(session);
}
}
结果如下:
Hibernate: select person0_.id as id0_0_, person0_.name asname0_0_, person0_.card_ID as card3_0_0_ from t_person person0_ whereperson0_.id=?
person.name=王五
Hibernate: select idcard0_.id asid1_1_, idcard0_.cardNo as cardNo1_1_, person1_.id as id0_0_, person1_.name asname0_0_, person1_.card_ID as card3_0_0_ from t_idCard idcard0_ left outer joint_person person1_ on idcard0_.id=person1_.id where idcard0_.id=?
person.cardNo=1111111111 这样的就找到了person对应的idcard,那能不能有idCard找到person呢?
public void testLoad2() {
Session session = null;
try {
session = HibernateUtils.getSession();
session.beginTransaction();
//
IdCard idCard = (IdCard)session.load(IdCard.class, 1);
System.out.println("idCard.cardNo=" + idCard.getCardNo());
System.out.println("idCard.person.name=" +idCard.getPerson().getName());
session.getTransaction().commit();
}catch(Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}finally {
HibernateUtils.closeSession(session);
}
}
结果如下:
Hibernate: select idcard0_.id as id1_1_, idcard0_.cardNo as cardNo1_1_,person1_.id as id0_0_, person1_.name as name0_0_, person1_.card_ID ascard3_0_0_ from t_idCard idcard0_ left outer join t_person person1_ onidcard0_.id=person1_.id where idcard0_.id=?
idCard.cardNo=1111111111
idCard.person.name=张三
结果对吗?
肯定不对,idCard.cardNo=1111111111这是王五的idCard,怎么查出来张三的呢?原因在于:
idCard的配置文件问题:
应该在idCard的配置文件的<one-to-one name="person" class="Person" />
修改为<one-to-one name="person" class="Person" property-ref="idCard"/>
因为:如果不修改则idCard会根据自己的id和person中的id比较(因为one-to-one是通过id查找到的),这样是不符合要求的,因为我们t_idcard中的id和t_person中 Card_ID相比较,这样的话可以通过
property-ref="idCard" 的设置找到t_person表中Card_ID和它作比较找到我们要找的数据。
分享到:
相关推荐
2. 选择合适的映射策略:理解懒加载、立即加载和集合的加载策略,避免N+1查询问题。 3. 优化查询:避免在HQL中使用子查询,尽量使用JOIN,合理设置缓存策略。 4. 谨慎使用事务:根据业务需求,正确设置事务隔离级别...
使用Hibernate可以显著提高开发效率,减少与数据库交互的代码量,但同时也需要注意性能优化,比如合理使用缓存、避免N+1查询等问题。总之,这个压缩包提供了一站式解决方案,让你能够快速开始使用Hibernate进行Java...
Hibernate支持多种关联映射,包括一对一(@OneToOne)、一对多(@OneToMany)、多对一(@ManyToOne)和多对多(@ManyToMany)。这些关联可以通过定义外键或使用中间表来实现,使得对象间的复杂关系得以轻松处理。 ...
10. **性能优化**: 在处理一对一关联时,需要注意避免N+1查询问题,通过合理使用JOIN查询或批处理可以提升性能。 **文件名称分析** "HibernateORM"这个文件名可能是包含示例代码、配置文件或教程文档的压缩包,...
1. **SessionFactory**:它是整个Hibernate的核心,负责实体类和数据库表之间的映射信息。SessionFactory是线程安全的,通常在应用启动时创建并全局共享。 2. **Session**:每个数据库操作都应在Session中进行,它...
Hibernate 3.6.10.Final引入了第一级缓存(Session级别)和第二级缓存(SessionFactory级别),有效减少对数据库的访问,提高系统性能。用户可以通过配置选择合适的缓存提供商,如 Ehcache 或 Infinispan。 九、...
- ** associations**:支持一对一、一对多、多对一、多对多等关系的映射。 3. **实际应用** - **实体类设计**:根据业务需求定义实体类,并使用Hibernate注解进行映射。 - **配置文件设置**:配置数据库连接、...
在这个“hibernate实例(一对多,多对一)”的主题中,我们将深入探讨两种重要的关联关系:一对一(One-to-One)和一对多(One-to-Many)。 **一对一关联(One-to-One)** 在一对一关联中,一个实体与另一个实体之间...
### Hibernate一对一关联映射原理 一对一关联映射是指在数据库中两个表之间存在一对一的关系,例如,一个人只有一个身份证,一个身份证也只属于一个人。在Hibernate中,我们可以通过@OneToOne注解来实现这种映射。 ...
4.1.4.Final版本是Hibernate发展的一个重要里程碑,它引入了许多新特性和改进,如更强大的查询语言HQL,以及对JPA标准的支持。 二、核心组件解析 1. SessionFactory:它是Hibernate的核心,负责管理所有实体类的元...
例如,假设有一个`Order`实体,它有一对多的关联关系到`Product`实体,我们想要获取所有订单及其对应的产品。如果我们先查询所有订单,然后在循环中为每个订单加载产品,那么对于N个订单,就会有N次额外的查询去获取...
总结来说,"hibernateORM1-n映射"是关于如何在Hibernate框架下建立和管理数据库中一对多关系的知识。理解和熟练运用这一映射机制,将有助于提高Java应用的数据库操作效率,减少代码量,增强程序的可维护性。通过正确...
本文将详细解析"hibernate一对多映射"的概念、配置及其实现过程,以帮助理解并掌握这一核心特性。 首先,我们要明白在关系型数据库中,"一对多"关系意味着一个实体(比如一个部门)可以有多个相关实体(如部门下的...
【标题】:“Hibernate一对一实例子”深入解析 在Java企业级开发中,数据持久化是一个不可或缺的部分,而Hibernate作为一款强大的对象关系映射(ORM)框架,极大地简化了这一过程。本篇将深入探讨 Hibernate 中的一...
6. **关系映射**:包括一对一、一对多、多对一和多对多的关系,使用@OneToOne, @OneToMany, @ManyToOne 和 @ManyToMany 注解来定义。 7. **懒加载(Lazy Loading)**:一种优化策略,关联的对象在需要时才从数据库...
九、多对一、一对多、多对多关系 Hibernate通过外键映射和集合映射处理这些关系,如@ManyToOne、@OneToMany、@ManyToMany等。 十、 Hibenate事件监听器 通过实现特定接口,如PreInsertEventListener,可以定制在...
- **一对一(OneToOne)**: 一个实体类实例对应数据库表的一行记录。 - **一对多(OneToMany)**: 一个实体类实例对应数据库表的多行记录。 - **多对一(ManyToOne)**: 多行记录对应数据库表的一个实体类实例。 - *...
本教程将深入探讨Hibernate中的四种主要数据关联:一对一(11)、多对一(M1)、一对多(1N)和多对多(MN)的关系映射。 1. **一对一(11)关联**: 在现实世界中,有些实体间存在一对一的关系,例如一个人只有一...
- 避免N+1查询问题:通过HQL的JOIN子句或Criteria的FetchMode.JOIN获取关联数据。 - 分页查询:使用Query的setFirstResult和setMaxResults方法,减少返回结果量。 通过深入理解Hibernate 4.3.9.Final,开发者可以...
2. 避免过多的懒加载:过度使用懒加载可能导致N+1查询问题,应合理设计数据模型和关联关系。 3. 使用预编译查询:Query的setParameters方法预编译参数,提升查询速度。 4. 事务边界合理划分:根据业务需求,正确设置...