近期我也是有点郁闷,究竟是程序中处理关联关系。还是直接使用外键处理关联关系呢?这个的说法不一致!程序中处理这样的关联关系的话。自己去维护这样的约束。这样的非常乐观的一种做法!或者是直接在数据库中处理这样的直接的外键关联,悲观的做法!刚刚看到个帖子。有的公司表中一个外键都没得。直接在程序中处理这样的关联关系。假设在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<>();
...
}

转载于:https://www.cnblogs.com/wzzkaifa/p/7354159.html

码农小汪-Hibernate学习8-hibernate关联关系注解表示@OneToMany mappedBy @ManyToMany @JoinTable...相关推荐

  1. 码农小汪-设计模式之-Builder模式

    建造者模式 将一个复杂的对象的构建与它的表示分离,使得同样构建的过程中可以创建不同的表示.这个话语看起来,好累啊!真心很难理解. 下面是它的UML图: 抽象建造者角色(Builder):为创建一个Pr ...

  2. 码农小汪-Volatile和Transient

    Volatile: Volatile修饰的成员变量在每次被线程访问时,都强迫从主内存中重读该成员变量的值.而且,当成员变量发生变化时,强迫线程将变化值回写到主内存.这样在任何时刻,两个不同的线程总是看 ...

  3. 码农小汪-设计模式之-命令模式

    大话设计模式的例子讲的非常的好,理解起来也方便!有时候忘了.想到这些特殊的例子感觉就是特别爽. 烤羊肉串带来的思考! 路边摊羊肉串: 老板,我这里排的比较先啊,我最先给钱.老板这个没有熟啊.我的是 辣 ...

  4. Hibernate学习之Hibernate注解总结

    Hibernate学习之Hibernate注解总结http://www.bieryun.com/3269.html 一.类级别的注解 @Entity name:表的名字(可选)一般表名和类名相同 必须 ...

  5. Hibernate学习5—Hibernate操作对象

    第一节:Hibernate 中四种对象状态 删除状态:处于删除状态的Java 对象被称为删除对象.比如说session delete一个对象,这个对象就不处于session缓存中了, 已经从sessi ...

  6. Hibernate学习之hibernate状态

    hibernate有三种状态,transient(瞬时状态),persistent(持久化状态)以及detached(离线状态),瞬时状态就是刚new出来一个对象,还没有被保存到数据库中,持久化状态就 ...

  7. Hibernate学习之hibernate.cfg.xml

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

  8. hibernate学习五 Hibernate补充

    1  MiddleGenIDE可以生成映射类和映射文件. 2 转载于:https://www.cnblogs.com/liufei1983/p/8635468.html

  9. 高效能码农的自我修养:5本书教你怎样科学学习,拒绝无用功

    导读:作为一枚苦逼的码农,你需要学习很多东西.但在开始的开始,你学会学习了吗?科学.高效的学习方法,会让你事半功倍.今天书单姐推荐5本书,为你带来26种黄金学习法则.11个高效能学习习惯.效率加法的2 ...

最新文章

  1. Android 10 vivo,更快更安全,vivo产品经理宣布:iQOO将首批适配Android 10正式版
  2. 强烈建议使用国外DNS解析域名,解决访问速度和某些访问故障!
  3. [转] 硬盘工具DiskMan使用图解
  4. C++面试常见问题一
  5. mysql sleep详解_MySQL中sleep函数的特殊现象示例详解
  6. C++课堂作业_02_PAT1025.反转链表
  7. apicloud退出app方法
  8. 《Java 就业培训教程》
  9. 迅雷iOS端安装 - iPhone安装手机迅雷
  10. 【数据处理】Python matplotlib绘制双柱状图以及绘制堆积柱状图——保姆级教程
  11. 速卖通店铺流量下滑什么原因,如何做提升?(测评补单)
  12. matlab离散系统的频率响应,离散系统的频率响应分析
  13. 解决笔记本HDMI外接显示器没声音的问题
  14. 夏季养生:一觉,二瓜,三汤,四穴,五果
  15. 关于SASL的介绍文档
  16. 计算机英语说明文,英语说明文
  17. 不愿意和别人打交道_一个人不愿意和同事打交道,大多是这3个原因,你了解吗...
  18. 微信发朋友圈/评论/点赞/搜索/购物车的测试点
  19. python-计算机视觉-OpenCV-调色板
  20. 2020茶艺师(中级)模拟考试及茶艺师(中级)模拟考试题库

热门文章

  1. ubuntu php 树莓派,树莓派3 安装ROS环境(ubuntu mate 16.04+kinetic)
  2. java中break标记的使用
  3. 硬件:台式机老式键盘知识科普
  4. 盘点2020 最烂密码大曝光,第一名的竟然是它?
  5. 【转载】一份完整的阿里云 Redis 开发规范,值得收藏!
  6. Win 10 终于干趴了 Win 7
  7. python循环顶帖_设计Python数据库连接池1-对象的循环引用问题
  8. Docker 安装nginx,并挂载文件
  9. 案例研究:设计与方法_如何进行1小时的重新设计(案例研究)
  10. 奥迪坚SVRM(Screen-Voice Recording Manager)录屏软件正式发布