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

眼前多少难甘事,自古男儿当自强。这篇文章主要讲述码农小汪-Hibernate学习8-hibernate关联关系注解表示@OneToMany mappedBy @ManyToMany @JoinTable相关的知识,希望能为你提供帮助。
近期我也是有点郁闷,究竟是程序中处理关联关系。还是直接使用外键处理关联关系呢?这个的说法不一致!程序中处理这样的关联关系的话。自己去维护这样的约束。这样的非常乐观的一种做法!或者是直接在数据库中处理这样的直接的外键关联,悲观的做法!刚刚看到个帖子。有的公司表中一个外键都没得。直接在程序中处理这样的关联关系。假设在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无需指定这个属性的。但在一些特殊的情况下,比如使用@[email  protected] 修饰 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_idagenameaddress_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_idperson_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-N1的一端要訪问N的一端。肯定的加个集合涩和前面的集合非常类似,可是如今的集合里的元素是关联的实体啦。对于单向的1—N关联关系。
仅仅须要在1的一端加入set类型的成员变量,记录全部的关联的实体。
即可了。具体怎么操作,我们慢慢的说来。
一个个字的打还是能够的。添加自己的理解
@OneToMany
级联。抓取,目标实体,mappedBy
无连接表的单向1-N1个人有多个住处~~~贪官!
不然怎么买的起这么多房子,如今的房价你又不是不知道。哼~
@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< > (); ... }

【码农小汪-Hibernate学习8-hibernate关联关系注解表示@OneToMany mappedBy @ManyToMany @JoinTable】这里是1对N 1个人有多个住的地方,可是每一个都是不一样的,所以要添加unique约束
由于採用连接表了,我们的Person表中没有存在维护连接关系,能够随意的持久化操作。

1个person2个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< > (); ... }


































    推荐阅读