在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 {
// ... 略
@OneToOn