Hibernate @OneToOne懒加载实现解决方案
在hibernate注解(三)中,我提高过一对一(@OneToOne)懒加载失效的问题。虽然给出了解决方法,但并没有给出完整的解决方案。今天我专门针对该问题进行讨论。至于懒加载失效的原因,在之前的文章中已经我已经叙述过了,就不再重复了,不明白的可以去看看。
一、测试环境
数据库:myqsl
代码:主:Student,从:Card
表:
-
DROP TABLE IF EXISTS `student`;
-
CREATE TABLE `student` (
-
`ID` int(11) NOT NULL,
-
`NAME` varchar(50) NOT NULL,
-
`CARD_ID` int(11) DEFAULT NULL,
-
PRIMARY KEY (`ID`),
-
KEY `PK_CARD_ID` (`CARD_ID`),
-
CONSTRAINT `PK_CARD_ID` FOREIGN KEY (`CARD_ID`) REFERENCES `card` (`ID`) ON DELETE NO ACTION ON UPDATE NO ACTION
-
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-
-
DROP TABLE IF EXISTS `card`;
-
CREATE TABLE `card` (
-
`ID` int(11) NOT NULL,
-
`CODE` varchar(32) NOT NULL,
-
PRIMARY KEY (`ID`)
-
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
代码:
-
package com.po;
-
-
import javax.persistence.CascadeType;
-
import javax.persistence.Column;
-
import javax.persistence.Entity;
-
import javax.persistence.FetchType;
-
import javax.persistence.GeneratedValue;
-
import javax.persistence.GenerationType;
-
import javax.persistence.Id;
-
import javax.persistence.JoinColumn;
-
import javax.persistence.OneToOne;
-
import javax.persistence.Table;
-
-
@Entity
-
@Table(name = "Student")
-
public class Student {
-
-
private int id;
-
private String name;
-
private Card card;
-
-
@Id
-
@GeneratedValue(strategy = GenerationType.IDENTITY)
-
@Column(name = "ID", unique = true, nullable = false)
-
public int getId() {
-
return id;
-
}
-
-
public void setId(int id) {
-
this.id = id;
-
}
-
-
@Column(name = "NAME", nullable = false, length = 50)
-
public String getName() {
-
return name;
-
}
-
-
public void setName(String name) {
-
this.name = name;
-
}
-
-
@OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
-
@JoinColumn(name = "CARD_ID")
-
public Card getCard() {
-
return card;
-
}
-
-
public void setCard(Card card) {
-
this.card = card;
-
}
-
}
-
package com.po;
-
-
import javax.persistence.CascadeType;
-
import javax.persistence.Column;
-
import javax.persistence.Entity;
-
import javax.persistence.FetchType;
-
import javax.persistence.GeneratedValue;
-
import javax.persistence.GenerationType;
-
import javax.persistence.Id;
-
import javax.persistence.OneToOne;
-
import javax.persistence.Table;
-
-
@Entity
-
@Table(name = "card")
-
public class Card {
-
-
private int id;
-
private String code;
-
private Student student;
-
-
@Id
-
@GeneratedValue(strategy = GenerationType.IDENTITY)
-
@Column(name = "ID", unique = true, nullable = false)
-
public int getId() {
-
return id;
-
}
-
-
public void setId(int id) {
-
this.id = id;
-
}
-
-
@Column(name = "CODE", length = 32, nullable = false)
-
public String getCode() {
-
return code;
-
}
-
-
public void setCode(String code) {
-
this.code = code;
-
}
-
-
@OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL, mappedBy = "card")
-
public Student getStudent() {
-
return student;
-
}
-
-
public void setStudent(Student student) {
-
this.student = student;
-
}
-
}
方案一
在card表增加一个student表的外键字段STUDENT_ID,并在Card类的@OneToOne下增加@JoinColumn(name = "STUDENT_ID"),去掉mappedBy = "card",即
-
DROP TABLE IF EXISTS `card`;
-
CREATE TABLE `card` (
-
`ID` int(11) NOT NULL,
-
`CODE` varchar(32) NOT NULL,
-
`STUDENT_ID` int(11) DEFAULT NULL,
-
PRIMARY KEY (`ID`),
-
KEY `PK_STUDENT_ID` (`STUDENT_ID`),
-
CONSTRAINT `PK_STUDENT_ID` FOREIGN KEY (`STUDENT_ID`) REFERENCES `student` (`ID`) ON DELETE NO ACTION ON UPDATE NO ACTION
-
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-
public class Card {
-
-
// ... 略
-
-
@OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
-
@JoinColumn(name = "STUDENT_ID")
-
public Student getStudent() {
-
return student;
-
}
-
-
// ... 略
-
}
优点:不改变Student与Card在代码中的对应关系(一对一)
缺点:需要同时维护Student和Card的两个外键。
方案二
改为主键关联。
-
DROP TABLE IF EXISTS `student`;
-
CREATE TABLE `student` (
-
`ID` int(11) NOT NULL,
-
`NAME` varchar(50) NOT NULL,
-
PRIMARY KEY (`ID`),
-
CONSTRAINT `PK_CARD_ID` FOREIGN KEY (`ID`) REFERENCES `card` (`ID`) ON DELETE NO ACTION ON UPDATE NO ACTION
-
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-
public class Student {
-
-
// ... 略
-
-
@Id
-
@GenericGenerator(name = "PK_Card", strategy = "foreign", parameters = @Parameter(name = "property", value = "card"))
-
@GeneratedValue(generator = "PK_Card")
-
@Column(name = "ID", unique = true, nullable = false)
-
public int getId() {
-
return id;
-
}
-
-
// ... 略
-
-
@OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL, optional = false)
-
@PrimaryKeyJoinColumn
-
public Card getCard() {
-
return card;
-
}
-
-
// ... 略
-
}
-
public class Card {
-
-
// ... 略
-
-
@OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL, mappedBy = "card", optional = false)
-
public Student getStudent() {
-
return student;
-
}
-
-
// ... 略
-
}
除了改变student表的主键、外键结构外,Student类和Card类也要做相应修改,尤其注意“optional”,要设置为false,否则无法实现懒加载。
优点:不改变Student与Card在代码中的对应关系(一对一)
缺点:改动较大,且使用主键关联具有局限性。
PS:主键关联的局限性
使用主键关联会影响数据存储结构,主键关联是一种强耦合,以上述为例:Card存在时,Student才能存在,Card消亡时,Student也随之消失。这是因为Student的主键依赖于Card主键,Student无法独立存在(就是说必须先有学生卡,才能有学生)。
方案三
将Card类中的OneToOne改为OneToMany(一对多)。
-
public class Card {
-
-
private Set students;
-
-
// ... 略
-
-
@OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL, mappedBy = "card")
-
public Set<Student> getStudents() {
-
return students;
-
}
-
-
public void setStudents(Set students) {
-
this.students = students;
-
}
-
-
// ... 略
-
}
优点:数据库不用修改
缺点:需要修改Student与Card在代码中的对应关系
方案四
放弃用注解的方式,改为Xml方式来实现hibernate模型设计,并在Card Xml的OneToOne标签中添加constrained属性,靠注解解决的办法已经没有了(instrument增强就算了吧,很麻烦)。
最后,我们来评估下以上方案的可行性。
方案一:从可读性来讲,是最容易理解的,但需要维护两个外键,如果程序控制不好的话,容易出问题,即关联错误。
方案二:主键关联虽然有些约束,但也取决于业务需求,比如订单和订单详情,采用主键关联也挺合适的,只是不适合相对灵活的对象关系。
方案三:改动在我看来是最小的了,牺牲了一定的可读性(关系从Card角度看变为了一对多),我个人比较喜欢该种方案,因此推荐。
方案四:如果不采用注解,而采用Xml的话,我是很推荐这种方案的,注解虽然优点多,也趋于主流,但最传统的Xml,功能还是最强大的。但如果你仅为了解决该问题,而将注解和Xml混合使用的话,我建议你还是放弃吧。
原文地址:https://blog.csdn.net/wangpeng047/article/details/19624795
Hibernate @OneToOne懒加载实现解决方案的更多相关文章
- hibernate的懒加载问题
产生原因: 当使用hibernate查询一个对象的时候,如果Session关闭,再调用该对象关联的集合或者对象的时候,会产生懒加载异常! 解决方案: 方案一: 在Session关闭之前,查询对象关联的 ...
- Android中ViewPager+Fragment取消(禁止)预加载延迟加载(懒加载)问题解决方案
转载请注明出处:http://blog.csdn.net/linglongxin24/article/details/53205878本文出自[DylanAndroid的博客] Android中Vie ...
- Hibernate的懒加载session丢失解决方法
在web.xml加入spring提供的过滤器,延长session的生命周期 <!--Hibernate的懒加载session丢失解决方法 --> <filter> <fi ...
- webpack多页面开发与懒加载hash解决方案
之前讨论了webpack的hash与chunkhash的区别以及各自的应用场景,如果是常规单页面应用的话,上篇文章提供的方案是没有问题的.但是前端项目复杂多变,应对复杂多页面项目时,我们不得不继续踩w ...
- Spring Boot JPA Entity Jackson序列化触发懒加载的解决方案
Spring Jpa这项技术在Spring 开发中经常用到. 今天在做项目用到了Entity的关联懒加载,但是在返回Json的时候,不管关联数据有没有被加载,都会触发数据序列化,而如果关联关系没有被加 ...
- hibernate的懒加载
WHY? WHAT? HOW? 所谓懒加载(lazy)就是延时加载,延迟加载.即不是不加载,而是在需要的时候才加载. 什么时候用懒加载呢,我只能回答要用懒加载的时候就用懒加载. 至于为什么要用懒加载呢 ...
- hibernate+spring mvc, 解决hibernate 对象懒加载 json序列化问题
引用地址 在使用Spring MVC时,@ResponseBody 注解的方法返回一个有懒加载对象的时候出现了异常,以登录为例: @RequestMapping("login") ...
- hibernate+spring mvc,解决hibernate对象懒加载,json序列化失败
在使用spring MVC时,@ResponseBody 注解的方法返回一个有懒加载对象的时候出现了异常,以登录为例: @RequestMapping("login") @Resp ...
- 过滤器解决hibernate中懒加载问题
使用过滤器解决懒加载问题需要我们对过滤器的生命周期有深刻的理解 1.浏览器发送一个请求 2.请求通过过滤器执行dofilter之前的代码 3.浏览器通过过滤器到达Servlet(注意我们这里的serv ...
随机推荐
- 【JZOJ4709】【NOIP2016提高A组模拟8.17】Matrix
题目描述 输入 输出 样例输入 4 3 5 4 1 7 3 4 7 4 8 样例输出 59716 数据范围 解法 40%暴力即可: 60%依然暴力: 100%依次计算第一行和第一列对答案的贡献即可: ...
- phpcms推送文章同时推送自定义字段
首先进入phpcms后台,模型管理-字段管理里,新建字段,新建字段必须是主表字段,如图所示 2 来到网站根目录,寻找phpcms\modules\content\classes\push_api.cl ...
- css 不大常见的属性(不断更新中...)
1 英语或数字强制换行 word-break:break-all; 2 使用具有回弹效果的滚动, 当手指从触摸屏上移开,内容会继续保持一段时间的滚动效果 -webkit-overflow-scroll ...
- 为什么要用Spring的依赖注入
最近写了一些Spring项目,用到了依赖注入,但是不知道为甚么要用,后来在知乎上看了一些大家的回答,觉得很精辟,遂简单总结一下. 主要是实现类之间的解耦,假如A类依赖B类,在实例化A类的话也要new一 ...
- Directx11教程(48) depth/stencil buffer的作用
原文:Directx11教程(48) depth/stencil buffer的作用 在D3D11中,有depth/stencil buffer,它们和framebuffer相对应,如下图所 ...
- MongoDB负载信息一目了然 阿里云HDM重磅发布MongoDB监控和诊断功能
混合云数据库管理(HDM)的统一监控.告警.诊断功能新增了对MongoDB的支持. 通过直观的方式将MongoDB多个维度的负载信息统一整合,不仅可以清晰的查看实时负载信息,也可以方便的确认历史负载情 ...
- bzoj1231 混乱的奶牛
Description 混乱的奶牛 [Don Piele, 2007] Farmer John的N(4 <= N <= 16)头奶牛中的每一头都有一个唯一的编号S_i (1 <= S ...
- EasyUI 网格 一主多从 从表使用自定义树状展开
<table id="Table1" class="easyui-datagrid" title="标题" style="w ...
- 关于Apple Watch,听听开发了两个月Watch App的工程师怎么说
今年1月份有幸应苹果邀请,秘密参与苹果 Watch App 的真机现场调试.4月份,Apple Watch 会正式上市.在这之前,也算是亲自抢先体验了 Apple Watch,以及开发了一下 Watc ...
- 2019-6-23-开源项目使用-appveyor-自动构建
title author date CreateTime categories 开源项目使用 appveyor 自动构建 lindexi 2019-06-23 11:47:40 +0800 2019- ...