Hibernate的关联映射——单向N-1关联
Hibernate的关联映射——单向N-1关联
N-1是非常常见的关联关系,最常见的父子关系也是N-1关联,单向的N-1关联只需从N的一端可以访问1的一端。
为了让两个持久化类能够支持这种关联映射,程序应该在N的一端的持久化类中增加一个属性,该属性引用1的一端的关联实体。
对于N-1关联(不论是单向关联还是双向关联),都需要在N的一端使用@ManyToOne修饰代表关联实体的属性。
1.无连接表的N-1关联
对于无连接表的N-1关联而言,程序只要在N的一端增加一列外键,让外键值记录该对象所属的实体即可,Hibernate可以使用@JoinColumn来修饰代表关联实体的属性,@JoinColumn用于映射底层的外键列。
直接使用@JoinColumn注解来映射N-1关联时,Hibernate将无需使用连接表,直接使用外键关联策略来处理这种关联映射。
(1)N的一端,不同的Person实体可以对应同一个Address实体
package com.mytest.test1; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.ManyToOne; import javax.persistence.Table; import org.hibernate.annotations.Cascade; import org.hibernate.annotations.CascadeType; /** * Person类中增加了一个Address类型的属性,引用关联的Address实体。 * 为了让Hibernate理解该Address类型的属性是关联实体,程序需要使用@ManyToOne、@JoinColumn修饰该属性
* 除此之外,还使用了@Cascade注解,该注解用于指定级联操作策略,此处的级联策略是CascadeType.ALL——这表明对Person实体的所有持久化操作都会
* 级联到它关联的Address实体 */ @Entity //标识这是一个持久化类 @Table(name="person1") //该持久化类对应表为person1 public class Person { @Id @Column(name="p_id") //设置为主键 此变量对应表中的p_id字段 @GeneratedValue(strategy=GenerationType.IDENTITY) //设置主键生成策略为自增长 private Integer id; @Column(name="p_name") //此变量对应表中的p_name字段 private String name; @Column(name="p_age") private Integer age; //此变量对应表中的p_age字段 //定义该Person实体关联的Address实体 @ManyToOne(targetEntity=Address.class) //映射外键列,指定外键列的列名为address_id,不允许为空 @JoinColumn(name="address_id",nullable=false) @Cascade(CascadeType.ALL) private Address address; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getAge() { return age; } public void setAge(int age) { this.age = age; } public Address getAddress() { return address; } public void setAddress(Address address) { this.address = address; } }
(2)1的一端,同一个Address可以被多个Person对应
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
/**
* 程序无需从Address访问Person,所以Address无须增加Person属性
*/
@Entity //指定该类为一个持久化类
@Table(name="add1") //对应的表名为add1
public class Address {
@Id @Column(name="address_id") //设置此属性为主键 对应表中的address_id字段
@GeneratedValue(strategy=GenerationType.IDENTITY) //设置主键的生成策略为自增长
private Integer addressId;
@Column(name="address_detail") //设置此属性对应表中的address_detail字段
private String addressDetail;
//无参数的构造器
public Address(){
}
//初始化所有成员变量的构造器
public Address(String addressDetail){
this.addressDetail = addressDetail;
}
public Integer getAddressId() {
return addressId;
}
public void setAddressId(Integer addressId) {
this.addressId = addressId;
}
public String getAddressDetail() {
return addressDetail;
}
public void setAddressDetail(String addressDetail) {
this.addressDetail = addressDetail;
}
}
(3)测试
import org.hibernate.Session;
import org.hibernate.Transaction;
public class Test1 {
public static void main(String[] args) {
Session session = HibernateUtil.currentSession();
Transaction tx = session.beginTransaction();
//创建一个Person对象
Person person = new Person();
//创建一个瞬态的Address对象
Address a = new Address("addressA");
//设置Person的各个属性
person.setName("liujiang");
person.setAge(24);
//设置Persion和Address之间的关联关系
person.setAddress(a);
//持久化Person对象
session.persist(person);
//创建一个瞬态的Address
Address b = new Address("addressB");
//修改持久化状态的Person对象
person.setAddress(b);
tx.commit();
HibernateUtil.closeSession();
}
}
2.有连接表的N-1关联
对于绝大部分单向N-1关联而言,使用基于外键关联的映射已经足够了。但由于底层数据库建模时也可以使用连接表来建立这种关联关系,因此Hibernate也为这种关联关系提供了支持。
如果需要使用连接表来映射单向N-1关联,程序需要显式使用@JoinTable注解来映射连接表。
@JoinTable专门用于映射底层连接表的信息。
多个Person实体可以通过连接表对应同一个Address实体 Address持久化类不变,再写一个Person1类,作为N一端的持久化类。
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.Table;
/**
* 有连接表的单向N-1
* Person为N的一端,多个Person实例可以对应同一个Address
* 除了使用@ManyToOne以外修饰代表关联实体的Address以外
* 还需要用@JoinTable注解显式的指定连接表
* 由于此映射N-1关联,因此程序还未该@JoinColumn增加了unique=true
*/
@Entity //指定该类是一个持久化类
@Table(name="person1") //指定该持久化类对应person1数据表
public class Person1 {
@Id @Column(name="p_id") //指定该属性为主键字段,对应数据表中的p_id字段
@GeneratedValue(strategy=GenerationType.IDENTITY) //设置主键的生成策略 这里为自增长
private Integer id; //id
@Column(name="p_name")
private String name; //name
@Column(name="age")
private Integer age; //age
//显式使用@JoinTable映射连接表
@JoinTable(
name="person1_address", // 指定连接表的表名为“person_address”
//指定连接表中person_id外键列,参照到当前实体对应表的主键列
joinColumns=@JoinColumn(
name="p_id",
referencedColumnName="p_id",
unique=true
),
//指定连接表中address_id为外键列,参照到当前实体的关联实体对应表的主键列
inverseJoinColumns=@JoinColumn(
name="address_id",
referencedColumnName="address_id"
)
)
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
}
在这种映射策略下,p_id是person1表的主键,同时也是person1_address表的主键,这保证了person1_address数据表中的p_id列不能出现重复值,也就保证了一个Person1实体最多只能关联一个Address实体。
对于使用连接表的N-1关联而言,由于两个实体对应的数据表都无需增加外键列,因此两个实体对应的数据表不存在主、从关系,程序完全可以想先持久化那个实体,就先持久化那个实体。无论顺序如何,程序都不会引发性能问题。
Hibernate的关联映射——单向N-1关联的更多相关文章
- Hibernate的关联映射——单向1-N关联
Hibernate的关联映射--单向1-N关联 单向1-N关联的持久化类里需要使用集合属性.因为1的一端需要访问N的一端,而N的一端将以集合(Set)形式表现.从这个意义上来看,1-N(实际上还包括N ...
- Hibernate的关联映射——单向1-1关联
Hibernate的关联映射--单向1-1关联 对于单向的1-1关联关系,需要在持久化类里增加代表关联实体的成员变量,并为该成员变量添加setter方法和getter方法.从持久化类的代码上看,单向1 ...
- hibernate之关于一对一单向,双向关联映射
[hibernate]之关于一对一单向,双向关联映射 首先我们来看,Hibernate官方对于一对一单向关联的解释: 基于外键关联的单向一对一关联和单向多对一关联差点儿是一样的. 唯一的不同就是单向一 ...
- 016 多对多关联映射 单向(many-to-many)
一般的设计中,多对多关联映射,需要一个中间表 Hibernate会自动生成中间表 Hibernate使用many-to-many标签来表示多对多的关联 多对多的关联映射,在实体类中,跟一对多一样,也是 ...
- (转)MyBatis框架的学习(五)——一对一关联映射和一对多关联映射
http://blog.csdn.net/yerenyuan_pku/article/details/71894172 在实际开发中我们不可能只是对单表进行操作,必然要操作多表,本文就来讲解多表操作中 ...
- 【Hibernate框架】关联映射(多对多关联映射)
按着我们的总结行进计划,接下来,就是有关于多对多映射的总结了. 我们来举个例子啊,很长时间以来,房价暴涨不落,但是还有很多人拥有很多套房产,假如说,一个富豪拥有九套房产,家里人么准去住哪一套,我们就以 ...
- 014 一对多关联映射 单向(one-to-many)
在对象模型中,一对多的关联关系,使用集合来表示. 实例场景:班级对学生:Classes(班级)和Student(学生)之间是一对多的关系. 多对一.一对多的区别: 多对一关联映射:在多的端加入一个外键 ...
- Hibernate框架关系映射一对多双向关联
直入主题,首先大配置常规配置, 这里住要说关联关系,大配置不多少,而且jar包默认添加好,笔者用的是idea2016. 然后我们知道关联关系主要是在小配置添加节点来配置属性.个人认为关联映射,就是对应 ...
- 论坛:一对一关联映射/单向关联/两个类间,可以有两个(多个)关联关系/content为大文本类型/
>>单向:只写一端的映射属性,另一端不写(有一端用不着);双向:两端都写映射属性 >>一对一关联有两类:一类基于主键的(一般不使用),一类基于外键的(重点学习): 外键:是一个 ...
随机推荐
- dede数据库类使用方法 $dsql
dedecms的数据库操作类,非常实用,在二次开发中尤其重要,这个数据库操作类说明算是奉献给大家的小礼物了. 引入common.inc.php文件 require_once (dirname(__FI ...
- prim算法
最小生成树 一个有 n 个结点的连通图的生成树是原图的极小连通子图,且包含原图中的所有 n 个结点,并且有保持图连通的最少的边.最小生成树可以用kruskal(克鲁斯卡尔)算法或prim(普里姆)算法 ...
- HDU 4358 Boring counting(莫队+DFS序+离散化)
Boring counting Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 98304/98304 K (Java/Others) ...
- smaller programs should improve performance
COMPUTER ORGANIZATION AND ARCHITECTURE DESIGNING FOR PERFORMANCE NINTH EDITION In this section, we l ...
- 小吐槽Toolbar
最近弄界面 要吧全部图标改成PNG格式 虽说从2010以后Delphi默认支持PNG格式图片, 但是想应用到按钮上, 似乎除了TButton意外, 也只能ToolBar可以正常显示了, 其他的, 比如 ...
- 阅读廖雪峰老师git教程笔记
1.首先git是目前世界上最先进的分布式版本控制系统之一.所谓版本控制是针对工作中一些普遍的现象的. 比如,你写一份文档,期间,不断的改善,每次修改都会进行备份,久而久之,会有很多版本的同一份文档,但 ...
- RESTful使用
测试工具: JMeter 可以使用JMeter对HTTP REST接口进行测试 Java RESTful框架: Jersey
- 将一个query后面的参数转为数组
function detailUri($params) { $returnParams = array(); if (isset($params)) { $arParams = explode(&qu ...
- freemarker学习
链接: http://swiftlet.net/archives/category/freemarker
- C# base64编码的文本与图片互转
/// <summary> /// base64编码的文本转为图片 /// </summary> /// <param name="txtFilePath&qu ...