Hibernate的单向N-1关联(一)
1. 无连接表的N-1关联
对于无连接的N-1关联而言,程序只要在N的一端增加一列外键,让外键记录对象指所属的实体即可,Hibernate可使用@JoinColumn来修饰代表关联实体的属性,@JoinColumn用于映射底层的外键列。下面定义一个Person的类,Person与Address的关系就是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实体@ManyToOne(targetEntity=Address.class)// 映射外键列,指定外键列的列名为address_id、不允许为空@JoinColumn(name="address_id" , nullable=false)@Cascade(CascadeType.ALL)private Address address;// id的setter和getter方法public void setId(Integer id){this.id = id;}public Integer getId(){return this.id;}// name的setter和getter方法public void setName(String name){this.name = name;}public String getName(){return this.name;}// age的setter和getter方法public void setAge(int age){this.age = age;}public int getAge(){return this.age;}// address的setter和getter方法public void setAddress(Address address){this.address = address;}public Address getAddress(){return this.address;}
}
程序无须从Address访问Person,所以Address无须增加Person属性。代码如下。
@Entity
@Table(name="address_inf")
public class Address
{// 标识属性@Id @Column(name="address_id")@GeneratedValue(strategy=GenerationType.IDENTITY)private int addressId;// 定义地址详细信息的成员变量private String addressDetail;// 无参数的构造器public Address(){}// 初始化全部成员变量的构造器public Address(String addressDetail){this.addressDetail = addressDetail;}// addressId的setter和getter方法public void setAddressId(int addressId){this.addressId = addressId;}public int getAddressId(){return this.addressId;}// addressDetail的setter和getter方法public void setAddressDetail(String addressDetail){this.addressDetail = addressDetail;}public String getAddressDetail(){return this.addressDetail;}
}
用如下的代码来保存Person和Address实体。
private void testCascase()
{Session session = HibernateUtil.currentSession();Transaction tx = session.beginTransaction();// 创建一个Person对象Person p = new Person();// 创建一个瞬态的Address对象Address a = new Address("广州天河"); // ①// 设置Person的name为owen.org字符串p.setName("owen.org");p.setAge(21);// 设置Person和Address之间的关联关系p.setAddress(a);// 持久化Person对象session.persist(p);// 创建一个瞬态的Address对象Address a2 = new Address("上海虹口"); // ②// 修改持久化状态的Person对象p.setAddress(a2); // ③tx.commit();HibernateUtil.closeSession();
}
上面的实体类中使用了@Cascade(CascadeType.ALL)修饰代表关联实体的属性,这意味着系统先自动级联插入主表记录,也就是先持久化Address对象,再持久化Person对象。也就是说,Hibernate先执行一条insert into address…,再执行一条insert into person….语句。而对于p.setAddress(a2),系统先执行insert into address…,后执行update person….。如果没有@Cascade(CascadeType.ALL),则会报TransientObjectException异常。如下是执行结果图。
2. 有连接表的N-1关联
在有连接的情况下会生成一张中间表,这个时候我们只要修Person的实体就行了,修饰如下。
@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;// id的setter和getter方法public void setId(Integer id){this.id = id;}public Integer getId(){return this.id;}// name的setter和getter方法public void setName(String name){this.name = name;}public String getName(){return this.name;}// age的setter和getter方法public void setAge(int age){this.age = age;}public int getAge(){return this.age;}// address的setter和getter方法public void setAddress(Address address){this.address = address;}public Address getAddress(){return this.address;}
}
其它的实体及执行的类如下。
public class PersonManager
{public static void main(String[] args){PersonManager mgr = new PersonManager();mgr.testPerson();HibernateUtil.sessionFactory.close();}private void testPerson(){Session session = HibernateUtil.currentSession();Transaction tx = session.beginTransaction();// 创建一个Person对象Person p = new Person();// 设置Person的name为owen字符串p.setName("owen");p.setAge(21);// 创建一个瞬态的Address对象Address a = new Address("广州天河");// 设置Person和Address之间的关联关系p.setAddress(a);// 再持久化Address对象session.persist(a);// 创建一个瞬态的Address对象Address a2 = new Address("上海虹口");// 设置Person和Address之间的关联关系p.setAddress(a2);// 由于采用了连接表来维护N-1关联关系,因此不存在主从表关系,// 程序可以随意控制先持久化哪个实体。// 持久化Address对象session.persist(a2);// 持久化Person对象session.save(p);// 持久化Address对象session.save(a);tx.commit();HibernateUtil.closeSession();}
}
执行结果如下。
Hibernate的单向N-1关联(一)相关推荐
- hibernate单向一对多关联
2019独角兽企业重金招聘Python工程师标准>>> 有这样一个应用场景,有一张用户表(APM_USER),一张部门表(APM_DEPT).用户和部门之间的关系是多对一(many ...
- jpa单向一对多关联映射
如果在一的@OneToMany有@manyToOne则是双向一对多关联,如果在多的那面没有@manyToOne关联则是单向一对多关联 class和student是一对多的关系 表结构 student ...
- Hibernate 之单向多对一映射及其衍生问题
由于在数据表之间可以通过外键进行关联,在使用Hibernate操作映射到存在关联关系的数据表的对象时,需要将对象的关联关系与数据表的外键关联进行映射. 首先建立hibernate.cfg.xml和会话 ...
- 06-hibernate注解-一对多单向外键关联
一对多单向外键 1,一方持有多方的集合,一个班级有多个学生(一对多). 2,@OneToMany(cascade={CascadeType.ALL}, fetch=FetchType.LAZY ) / ...
- hibernate 一对多(one-to-many)双向关联
一对多(one-to-many)双向关联实例(Department- Employee) 这里的一对多双向关联是在域模型(实体对象模型)上的概念,在关系数据库中,只存在外键参照关系,而且总是由&quo ...
- Hibernate学习之一对多关联
注意事项: 1.单向一对多 只需在"一"放进行配置 2.双向一对多 需要在关联双方都加以配置,而且需要在一的一方设置inverse=true 首先是实体类: TAddress ...
- hibernate映射-单向n-n关联关系
(学习记录,错误不足之处,请您耐心指正^_^) hibernate映射-多对多关联关系 n-n关联必须使用连接表才能完成, 一.代码示例: {类文件↓} Category.class 1 packag ...
- hibernate的一对多双向关联映射----客户和订单关系
客户和订单关系:客户是一的一方,订单是多的一方. customer表: CREATE TABLE `customer` ( `ID` int(4) NOT NULL AUTO_INCREMENT , ...
- hibernate one2one 唯一外键关联(双向关联)
hibernate的一对一唯一外键关联映射(双向关联 Person <------->IdCard) 一对一唯一外键关联采用<one - to -one>标签映射,必须指定标签 ...
- hibernate映射(单向双向的一对多、多对一以及一对一、多对一(转)
多对一关联映射:在多的一端加入一个外键指向一的一端,它维护的关系是多指向一 一对多关联映射:在多的一端加入一个外键指向一的一端,它维护的关系是一指向多 也就是说一对多和多对一的映射策略是一样的,只是站 ...
最新文章
- ROC曲线与癌症分类
- 计算机和打印机的耗材管理,打印设备耗材余量知多少?多种途径实时掌握
- CNCF宣布containerd毕业
- 使用Spring AOP中MethodInterceptor记录日志
- 【Nutch2.2.1基础教程之1】nutch相关异常
- linux远程连接交换机,思科:路由器、交换机 ssh远程连接
- Java 开源Wiki:XWiki
- Echarts数据可视化event图表事件的相关操作,开发全解+完美注释
- python下文件以及文件的常用操作-1
- curl语句导入到Postman
- java海贼王秘宝传说下载,《梦想海贼王》全套源码
- C#加密Excel文件
- 大前端学习笔记--持续随缘更新
- 洛谷P1010 [NOIP1998 普及组] 幂次方 C语言/C++
- BAT批处理批量修改文件后缀名
- (Android版)AR 现实增强 高通 Vuforia QCAR SDK学习笔记(一)
- 笔记本 android,震惊:这个秘籍可以让笔记本同时拥有(mac/win/Android)系统
- JAVA架构师面试分享—链家网
- iOS 屏幕实时共享功能实践(内附详细代码)
- 广州联通用户开通GPRS上网流量包月如意通上网王本地王