近期我也是有点郁闷,究竟是程序中处理关联关系。还是直接使用外键处理关联关系呢?这个的说法不一致!程序中处理这样的关联关系的话。自己去维护这样的约束。这样的非常乐观的一种做法!或者是直接在数据库中处理这样的直接的外键关联,悲观的做法!刚刚看到个帖子。有的公司表中一个外键都没得。直接在程序中处理这样的关联关系。假设在Hibernate中处理外键关系的话。我们首先得有个主表的对象吧,然后在创建外键。感觉有点啰嗦。为啥不直接操作呢!

我仅仅要晓得你这个Id是外键即可了。各有各的说法。我想你也在思考这个问题。

现实的世界中确实非常少有孤立纯在的东西。大多都是两者之间纯在某种关系的。有单向关系 仅仅能通过老师訪问学生。或者学生訪问老师

或者双向关系 两个都能够相互的訪问

单向关系

1-1

1-N

N-1

N-N

双向关系

1-1

1-N

N-N

单向N_1关联是最多的,多个人住同一个地址。我们仅仅须要从人这一端知道他的住址即可了,不是必需知道某个地址的用户。

为了让我们两个持久化实体关联。程序在N的一端添加持久化实体的一个属性,该属性指向引用1的那一端的关联实体

对于N-1(不管是单向关联还是双向关联),都仅仅须要在N的一端使用@ManyToONe修饰关联实体的属性

有以下的一些属性,事实上之前我也说过的,非常easy忘记。没事的时候自己看看

属性 说明
Cascade 级联操作策略CascadeType.ALL….
Fetch 抓取关联实体的策略,之前说过FechType.Lazy 延迟和马上
targetEntity 该属性的关联实体的类名,在默认情况下通过反射获得类名

默认情况下我们的targetEntity无需指定这个属性的。但在一些特殊的情况下,比如使用@OneToMany.@ManyToMany 修饰 1-N N-N关联的时候。关联实体集合不带泛型信息就必须指定了

无连接的N-1

无连接也就是不须要第三张表,维护我们的关联关系。对于N_1关联关系,我们仅仅须要在N的一端添加一列外键即可。

让外键的值记录到该属性的实体即可。

Hibernate使用@JoinColumn来修饰代表关联实体的属性,用于映射底层的外键列。

这样的就不使用连接表了

好啦,我们看一下样例

多个人相应同一个地址

@Entity
@Table(name="person_inf")
public class Person
{
@Id @Column(name="person_id")
@GeneratedValue(strategy=GenerationType.IDENTITY)
private Integer id;
private String name;
private int age;
// 定义该Person实体关联的Address实体
@ManyToOne(targetEntity=Address.class)
// 映射外键列,指定外键列的列名为address_id、不同意为空
@JoinColumn(name="address_id" , nullable=false)
@Cascade(CascadeType.ALL)
private Address address;
........
} Address 里面非常正常就一个Id。和地址具体

他们建立的表什么样子呢?

person_inf

person_id age name address_id

address_inf

address_id addressDetail

怎样操作对象呢,由于address_id 是一个外键。

假设我们保存一个Person对象在我们的表中的话。我们应该首先有一个Address 对象吧。

能够是存在数据库中的。也能够才瞬态对象。我们在插入的时候级联操作。会先插入address_inf这个表中,然后才干够使用外接啦。不然会报错的,由于没有存在的外键,肯定不行啦~

Session session = HibernateUtil.currentSession();
Transaction tx = session.beginTransaction();
// 创建一个Person对象
Person p = new Person();
// 创建一个瞬态的Address对象
Address a = new Address("广州天河");
p.setName("Test");
p.setAge(21);
// 设置Person和Address之间的关联关系
p.setAddress(a);
// 持久化Person对象
session.persist(p);//级联的插入操作哦~。地址一定先于person插入数据表中,这里必须设置级联操作,不然要报错
// 创建一个瞬态的Address对象
Address a2 = new Address("上海虹口");
// 改动持久化状态的Person对象
p.setAddress(a2);
tx.commit();
HibernateUtil.closeSession();

有连接的N-1

我们的关联关系的维护让第三张表来维护啦。

对于大部分的N_1单向关系,仅仅要基于外键的关联关系维护已经够了。

假设有须要使用连接表来维护关联关系,程序能够使用连接表显示的维护这样的关系,所谓连接表就是建立第三张表格来维护我们的关系即可了。使用@JoinTable

以下的是java给的样例,除了这些属性外,我们还能够指定targetEntity。指定关联的实体是哪个!

也就是生成表的是哪个表所相应的实体。

 @JoinTable(
name="CUST_PHONE",
//相对于当前实体的外键,的列名。 參照的列名,也就是数据表中的名字
joinColumns=
@JoinColumn(name="CUST_ID", referencedColumnName="ID"),
//这个也是个外键,仅仅是不说当前实体里面的属性。
inverseJoinColumns=
@JoinColumn(name="PHONE_ID", referencedColumnName="ID")
)

我们来看个样例就知道啦

@Entity
@Table(name="person_inf")
public class Person
{
// 标识属性
@Id @Column(name="person_id")
@GeneratedValue(strategy=GenerationType.IDENTITY)
private Integer id;
private String name;
private int age;
// 定义该Person实体关联的Address实体
@ManyToOne(targetEntity=Address.class)
// 显式使用@JoinTable映射连接表
@JoinTable(name="person_address", // 指定连接表的表名为person_address
// 指定连接表中person_id外键列,參照到当前实体相应表的主键列
joinColumns=@JoinColumn(name="person_id"
, referencedColumnName="person_id", unique=true),
// 指定连接表中address_id外键列,參照到当前实体的关联实体相应表的主键列
inverseJoinColumns=@JoinColumn(name="address_id"
, referencedColumnName="address_id")
)
private Address address;
.....
@Entity
@Table(name="address_inf")
public class Address
{
// 标识属性
@Id @Column(name="address_id")
@GeneratedValue(strategy=GenerationType.IDENTITY)
private int addressId;
// 定义地址具体信息的成员变量
private String addressDetail;
}

这里产生的表的话,曾经的person的表不会改变address也不会变

仅仅是添加一个外表

person_address ——table

address_id person_id

使用连接表维护关系

单向1-1关联

看上去 1-1 和N-1 几乎相同啊,都须要在持久化实体中添加代表关联实体的成员变量,从代码上看没得什么差别。由于N的一端和1的一端都能够直接的訪问关联的实体,。

不管单向的还是双向的1-1关联,都须要使用@OneToOne修饰关联实体的属性

有以下的

级联操作,抓取属性。optional 关联关系是否可选。目标关联实体的类名targetEntity.还有个重要的

mappedBy:该属性合法的属性值为关联实体的属性名该属性指定关联实体中的哪个属性可引用当前的实体

样例:基于外键的单向 1-1 关联,无连接表

@Entity
@Table(name="person_inf")
public class Person
{
// 标识属性
@Id @Column(name="person_id")
@GeneratedValue(strategy=GenerationType.IDENTITY)
private Integer id;
private String name;
private int age;
// 定义该Person实体关联的Address实体
@OneToOne(targetEntity=Address.class)
// 映射名为address_id的外键列,參照关联实体相应表的addres_id主键列
@JoinColumn(name="address_id"
, referencedColumnName="address_id" , unique=true)
private Address address;
地址肯定是独一无二的嘛,对不正确!添加unique约束~
.....
}

有连接表的也是几乎相同,理解啦买即可了

@Entity
@Table(name="person_inf")
public class Person
{
// 标识属性
@Id @Column(name="person_id")
@GeneratedValue(strategy=GenerationType.IDENTITY)
private Integer id;
private String name;
private int age;
// 定义该Person实体关联的Address实体
@OneToOne(targetEntity=Address.class)
@JoinTable(name="person_address",
joinColumns=@JoinColumn(name="person_id"
, referencedColumnName="person_id" , unique=true),
inverseJoinColumns=@JoinColumn(name="address_id"
, referencedColumnName="address_id", unique=true)
)
private Address address;
......
}

上面的东西,我相信仅仅要第一个看懂了即可了,跟着画样子涩。1-1嘛。肯定不能一样的涩。

单向的1-N

1的一端要訪问N的一端。肯定的加个集合涩和前面的集合非常类似,可是如今的集合里的元素是关联的实体啦。对于单向的1—N关联关系。

仅仅须要在1的一端加入set类型的成员变量,记录全部的关联的实体。

即可了。具体怎么操作,我们慢慢的说来。

一个个字的打还是能够的。添加自己的理解

@OneToMany

级联。抓取,目标实体,mappedBy

无连接表的单向1-N

1个人有多个住处~~~贪官!

不然怎么买的起这么多房子,如今的房价你又不是不知道。哼~

@Entity
@Table(name="person_inf")
public class Person
{
@Id @Column(name="person_id")
@GeneratedValue(strategy=GenerationType.IDENTITY)
private Integer id;
private String name;
private int age;
// 定义该Person实体全部关联的Address实体,没有指定cascade属性
@OneToMany(targetEntity=Address.class)
// 映射外键列。此处映射的外键列将会加入到关联实体相应的数据表中。为啥呢?
@JoinColumn(name="person_id" , referencedColumnName="person_id")
private Set<Address> addresses
= new HashSet<>();
........
}

这里的外键列不会添加到当前实体相应的数据表中,而是添加到,关联实体Address相应的数据表中,有点特殊!

为什么。之前我们使用set集合的时候都必须在添加一个表记得?仅仅只是这里添加到了关联实体里面去了。

而不是在添加一张表~~

N的端不维护关系,没得变化~

有连接的1-N

@Entity
@Table(name="person_inf")
public class Person
{
// 标识属性
@Id @Column(name="person_id")
@GeneratedValue(strategy=GenerationType.IDENTITY)
private Integer id;
private String name;
private int age;
// 定义该Person实体全部关联的Address实体
@OneToMany(targetEntity=Address.class)
// 映射连接表为person_address
@JoinTable(name="person_address",
// 定义连接表中名为person_id的外键列。该外键列參照当前实体相应表的主键列
joinColumns=@JoinColumn(name="person_id"
, referencedColumnName="person_id"),
// 定义连接表中名为address_id的外键列。
// 该外键列參照当前实体的关联实体相应表的主键列
inverseJoinColumns=@JoinColumn(name="address_id"
, referencedColumnName="address_id", unique=true)
)
private Set<Address> addresses
= new HashSet<>();
...
}

这里是1对N 1个人有多个住的地方,可是每一个都是不一样的,所以要添加unique约束

由于採用连接表了,我们的Person表中没有存在维护连接关系,能够随意的持久化操作。



1个person 2个adress 要插入5次操作哦

自己想想为什么?

单向的N-N也是须要的

@ManyToMany

N-N关系必须须要连接表啦,和有连接的1-N类似,可是要把unique约束去掉啦~

直接改动啦,上面那个~

@Entity
@Table(name="person_inf")
public class Person
{
// 标识属性
@Id @Column(name="person_id")
@GeneratedValue(strategy=GenerationType.IDENTITY)
private Integer id;
private String name;
private int age;
// 定义该Person实体全部关联的Address实体
@ManyToMany(targetEntity=Address.class)
// 映射连接表为person_address
@JoinTable(name="person_address",
// 定义连接表中名为person_id的外键列,该外键列參照当前实体相应表的主键列
joinColumns=@JoinColumn(name="person_id"
, referencedColumnName="person_id"),
// 定义连接表中名为address_id的外键列,
// 该外键列參照当前实体的关联实体相应表的主键列
inverseJoinColumns=@JoinColumn(name="address_id"
, referencedColumnName="address_id")
)
private Set<Address> addresses
= new HashSet<>();
...
}

码农小汪-Hibernate学习8-hibernate关联关系注解表示@OneToMany mappedBy @ManyToMany @JoinTable的更多相关文章

  1. 码农小汪-spring框架学习之2-spring IoC and Beans 控制反转 依赖注入 ApplicationContext BeanFactory

    spring Ioc依赖注入控制反转 事实上这个东西很好理解的,并非那么的复杂. 当某个Java对象,须要调用还有一个Java对象的时候(被依赖的对象)的方法时.曾经我们的做法是怎么做呢?主动的去创建 ...

  2. Hibernate学习0.Hibernate入门

    Hibernate是什么 面向java环境的对象/关系数据库映射工具. 1.开源的持久层框架. 2.ORM(Object/Relational Mapping)映射工具,建立面向对象的域模型和关系数据 ...

  3. Hibernate学习笔记-Hibernate HQL查询

    Session是持久层操作的基础,相当于JDBC中的Connection,通过Session会话来保存.更新.查找数据.session是Hibernate运作的中心,对象的生命周期.事务的管理.数据库 ...

  4. hibernate学习之Hibernate API

    1. Hibernate Api分类 1)提供访问数据库的操作(如保存,更新,删除,查询)的接口.这些接口包括:Session, Transaction,,Query接口. 2)由于配置Hiberna ...

  5. Hibernate学习之Hibernate流程

    Hibernate的核心组件 在基于MVC设计模式的JAVA WEB应用中,Hibernate可以作为模型层/数据访问层.它通过配置文件(hibernate.properties或hibernate. ...

  6. Hibernate学习之——Hibernate环境搭建

    之前在写关于安卓闹钟的教程,写了一半就没后一半了,其实自己也没做好,在校外实习,校内毕业实习又有任务,只能先放放了,等毕业实习结束之后,在继续安卓闹钟开发之旅,相信这个时间不会很久的.现在毕业实习用到 ...

  7. Hibernate学习(五)Hibernate 多对多映射

    说到多对多关系,印象最深刻的就是大学的选修课.一个学生可以选修多门课程,一门课程可以有多个学生选修,学生所选的每一门课程还有成绩.这个场景的E-R图如下: 对于多对多的关系,我们通常会抽出一张中间表( ...

  8. Hibernate学习之hibernate.cfg.xml

    <?xml version='1.0' encoding='UTF-8'?> <!DOCTYPE hibernate-configuration PUBLIC "-//Hi ...

  9. Hibernate学习笔记-Hibernate关系映射

    1. 初识Hibernate——关系映射 http://blog.csdn.net/laner0515/article/details/12905711 2. Hibernate 笔记8 关系映射1( ...

随机推荐

  1. php批量删除数据库下指定前缀的表

    如何用php批量删除数据库下所有前缀为prefix_的表. 例子,统一删除前缀为“prefix_”的表. <?php //设置数据库连接信息.数据库服务器地址,数据库用户名,数据密码 mysql ...

  2. 【Android】Java堆栈溢出的解决办法

    分类:C#.Android.VS2015: 创建日期:2016-03-18 随着项目中添加的.jar和.so文件越来越多,编译MyDemos项目时,可能会出现Java堆栈溢出的错误,提示让增加Java ...

  3. 【Android】20.4 录音

    分类:C#.Android.VS2015: 创建日期:2016-03-13 一.简介 利用Android提供的MediaRecorder类可直接录制音频. 1.权限要求 录制音频和视频需要下面的权限: ...

  4. linux下使用shell脚本自动化部署项目

    在Java开发项目时经常要把正在开发的项目发布到测试服务器中去测试,一般的话是要把项目先打成war包,然后把war包发布到服务器中,关闭服务器, 最后重新启动服务器,虽然这过程不是很繁琐,但如果是多个 ...

  5. JVM ,Java paper

    http://files.cnblogs.com/files/WCFGROUP/IntroductiontoCompilerConstructioninaJavaWorld.pdf A Fast Wr ...

  6. linux下调试core的命令

    在程序不寻常退出时,内核会在当前工作目录下生成一个core文件(是一个内存映像,同时加上调试信息).使用gdb来查看core文件,可以指示出导致程序出错的代码所在文件和行数. 1.core文件的生成开 ...

  7. hdoj 2717 Catch That Cow

    Problem Description Farmer John has been informed of the location of a fugitive cow and wants to cat ...

  8. 【转】批量删除redis中的key

    1. DEL 直接加键名称 DEL key1 key2 key3 127.0.0.1:6379>  DEL site_msg_99973  false site_msg_99974   fals ...

  9. Python中关于类和函数的初体验之"__init__"和"__str__"不是"_init_"和"_str_"

    刚刚接触Python,今天就是怎么也调试不过去了,上网上查直到晚上才查到一个有效信息,真是坑啊!原来Python中的这些“魔法”方法的命名里就有陷阱…… 上图中的那两个红圈圈,一定要记住哦,这些Pyt ...

  10. java Spring 事务的初次使用与验证

    事务,只要是为了保证数据的原子性.避免出现脏数据. 下面来讲解下spring是如何使用事务的. 1.配置事务.这里采用的是注解的模式 <!-- 配置事务管理器 ,如果你暂时未使用到事务可以不配置 ...