hibernate的OneToOne映射
1、前言
@OneToOne注解可以建立实体bean之间的一对一的关联。 一对一关联有四种情况:
一是关联的实体都共享同样的主键;
二是其中一个实体通过外键关联到另一个实体的主键 (注意要模拟一对一关联必须在外键列上添加唯一约束);
三是通过关联表来保存两个实体之间的连接关系 (注意要模拟一对一关联必须在每一个外键上添加唯一约束);
以上三种情况在源码中可见说明,但其实在实际开发过程中,总会有第四种情况:两个实体类只是通过两个普通字段关联(外键关联的特殊案例)。
2、共享主键
通过共享主键来进行一对一关联映射。
单向关联
entity:Body
@Entity
@Data
@Table(name = "jei_body")
public class Body implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "id")
@ApiModelProperty(value = "id")
private Long id;
@Column(name = "name")
@ApiModelProperty(value = "姓名")
private String name;
@Column(name = "gender")
@ApiModelProperty(value = "性别")
private Integer gender;
@OneToOne(fetch = FetchType.LAZY)
@PrimaryKeyJoinColumn
private Heart heart;
}
注意:
@OneToOne(fetch = FetchType.LAZY)
@PrimaryKeyJoinColumn
使用注解@PrimaryKeyJoinColumn定义了一对一关联。
双向关联
entity:Heart
@Entity
@Data
@Table(name = "jei_heart")
public class Heart implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "id")
@ApiModelProperty(value = "id")
private Long id;
@Column(name = "is_health")
@ApiModelProperty(value = "是否健康")
private String isHealth;
@OneToOne(fetch = FetchType.LAZY, mappedBy = "heart")
private Body body;
}
注意:
@OneToOne(fetch = FetchType.LAZY, mappedBy = "heart")
这里就不再需要@PrimaryKeyJoinColumn进行定义关联,需要用mappedBy 来确定关系由谁来维护。mappedBy="heart"说明在两个关联的实体Bean中,body这一端是关系的拥有者。如果mappedBy没有写的话,hibernate会自动在heart表中生成body_id字段(关联表名_id),否则运行代码就会报错:Unknown column 'heart0_.body_id' in 'field list'
其它
查询body
查询heart
3、外键关联
通过外键关联需要区别主表和副表(要求主表的非主键列(如果它是主键的话,就是”共享主键“)是副表的主键),当然它们是可以对调角色的,只是观察的角度不同。
单向关联
entity:Person
@Entity
@Data
@Table(name = "jei_person")
public class Person implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
@ApiModelProperty(value = "id")
private Long id;
@Column(name = "name")
@ApiModelProperty(value = "姓名")
private String name;
@Column(name = "card_id")
@ApiModelProperty(value = "身份证id")
private Long cardId;
@OneToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "card_id", referencedColumnName = "id", insertable = false, updatable = false)
private Card card;
}
注意:
@OneToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "card_id", referencedColumnName = "id", insertable = false, updatable = false)
这里的name=“card_id”, 指的当前表的字段(可以是任意名字的字段),referencedColumnName = "id"是副表的主键id,其它这里可以不写referencedColumnName ,因为它默认而且必须是副表的主键id。
双向关联
entity:Card
@Entity
@Data
@Table(name = "jei_card")
public class Card implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
@ApiModelProperty(value = "id")
private Long id;
@Column(name = "county_name")
@ApiModelProperty(value = "县、市辖区、县级市、自治县、旗、自治旗、特区、林区名称")
private String countyName;
@Column(name = "detail")
@ApiModelProperty(value = "身份证明细")
private String detail;
@OneToOne(fetch = FetchType.LAZY, mappedBy = "card")
private Person person;
}
注意:
@OneToOne(fetch = FetchType.LAZY, mappedBy = "card")
这里副表就不再需要@JoinColumn进行声明关联,需要用mappedBy 来确定关系由谁来维护。mappedBy="card"说明在两个关联的实体Bean中,person这一端是关系的拥有者,person一方的表中生成到关联类的外键。
其它
它们分别关联查询的sql截图。
查询person
查询card
4、关联表
通过关联表来保存两个实体之间的连接关系,也许是最另类的,也是很常见的。
单向关联
entity:Customer
@Entity
@Data
@Table(name = "jei_customer")
public class Customer implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
@ApiModelProperty(value = "id")
private Long id;
@Column(name = "name")
@ApiModelProperty(value = "姓名")
private String name;
@Column(name = "gender")
@ApiModelProperty(value = "性别")
private Integer gender;
@OneToOne(fetch = FetchType.LAZY)
@JoinTable(name = "jei_customer_and_passport",
joinColumns = @JoinColumn(name = "customer_id"),
inverseJoinColumns = @JoinColumn(name = "passport_id"))
private Passport passport;
}
注意:
@OneToOne(fetch = FetchType.LAZY)
@JoinTable(name = "jei_customer_and_passport",joinColumns = @JoinColumn(name = "customer_id"),inverseJoinColumns = @JoinColumn(name = "passport_id"))
Customer通过名为 jei_customer_and_passport表和 Passport关联,该关联表(jei_customer_and_passport)拥有名为passport_id的外键列,该 外键指向Passport,该信息定义为inverseJoinColumn的属性值,而customer_id外键列指向Customer, 该信息定义为 joinColumns的属性值。
双向关联
entity:Passport
@Entity
@Data
@Table(name = "jei_passport")
public class Passport implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "id")
@ApiModelProperty(value = "id")
private Long id;
@Column(name = "country")
@ApiModelProperty(value = "国家")
private String country;
@Column(name = "is_effect")
@ApiModelProperty(value = "是否有效")
private Integer isEffect;
@OneToOne(fetch = FetchType.LAZY, mappedBy = "passport")
private Customer customer;
}
注意:
@OneToOne(fetch = FetchType.LAZY, mappedBy = "passport")
这里不需要@JoinTable进行声明关联,需要用mappedBy 来确定关系由谁来维护。mappedBy="passport"说明在两个关联的实体Bean中,customer这一端是关系的拥有者。
其它
查询customer
查询passport
5、只是普通字段关联
它其实也是一种外键关联,只是说关联字段没有一个是主键;这样的关联关系,推荐只做单向关联。
单向关联
entity:Teacher
@Entity
@Data
@Table(name = "jei_teacher")
public class Teacher implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "id")
@ApiModelProperty(value = "id")
private Long id;
@Column(name = "name")
@ApiModelProperty(value = "姓名")
private String name;
@Column(name = "course")
@ApiModelProperty(value = "课程")
private String course;
@Column(name = "student_relation_id")
@ApiModelProperty(value = "关系id")
private Long studentRelationId;
@OneToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "student_relation_id", referencedColumnName = "teacher_relation_id", insertable = false, updatable = false)
@NotFound(action = NotFoundAction.IGNORE)
private Student student;
}
注意:
@OneToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "student_relation_id", referencedColumnName = "teacher_relation_id", insertable = false, updatable = false)
@NotFound(action = NotFoundAction.IGNORE)
这里的name=“student_relation_id”, 指的当前表的字段,referencedColumnName = "teacher_relation_id"是关联表的字段,推荐要加上@NotFound(action = NotFoundAction.IGNORE),这时一定是@OneToOne(fetch = FetchType.EAGER),否则有会警告。
双向关联
entity:Student
@Entity
@Data
@Table(name = "jei_student")
public class Student implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
@ApiModelProperty(value = "id")
private Long id;
@Column(name = "name")
@ApiModelProperty(value = "姓名")
private String name;
@Column(name = "address")
@ApiModelProperty(value = "地址")
private String address;
@Column(name = "teacher_relation_id")
@ApiModelProperty(value = "关系id")
private Long teacherRelationId;
@OneToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "teacher_relation_id", referencedColumnName = "student_relation_id", insertable = false, updatable = false)
@NotFound(action = NotFoundAction.IGNORE)
private Teacher teacher;
// 这种是要报错的
// @OneToOne(fetch = FetchType.LAZY, mappedBy = "student")
// private Teacher teacher;
}
注意:
@OneToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "teacher_relation_id", referencedColumnName = "student_relation_id", insertable = false, updatable = false)
@NotFound(action = NotFoundAction.IGNORE)
这里的name=“teacher_relation_id”, 指的当前表的字段,referencedColumnName = "student_relation_id"是关联表的字段,推荐要加上@NotFound(action = NotFoundAction.IGNORE),这时一定是@OneToOne(fetch = FetchType.EAGER),否则有会警告。
其它
查询teacher
select teacher0_.id as id1_10_, teacher0_.course as course2_10_, teacher0_.name as name3_10_, teacher0_.student_relation_id as student_4_10_ from jei_teacher teacher0_ where teacher0_.id=1 and (teacher0_.name like ?) and (teacher0_.course like ?) and teacher0_.student_relation_id=100
select student0_.id as id1_9_2_, student0_.address as address2_9_2_, student0_.name as name3_9_2_, student0_.teacher_relation_id as teacher_4_9_2_, teacher1_.id as id1_10_0_, teacher1_.course as course2_10_0_, teacher1_.name as name3_10_0_, teacher1_.student_relation_id as student_4_10_0_, student2_.id as id1_9_1_, student2_.address as address2_9_1_, student2_.name as name3_9_1_, student2_.teacher_relation_id as teacher_4_9_1_ from jei_student student0_ left outer join jei_teacher teacher1_ on student0_.teacher_relation_id=teacher1_.student_relation_id left outer join jei_student student2_ on teacher1_.student_relation_id=student2_.teacher_relation_id where student0_.teacher_relation_id=?
select teacher0_.id as id1_10_2_, teacher0_.course as course2_10_2_, teacher0_.name as name3_10_2_, teacher0_.student_relation_id as student_4_10_2_, student1_.id as id1_9_0_, student1_.address as address2_9_0_, student1_.name as name3_9_0_, student1_.teacher_relation_id as teacher_4_9_0_, teacher2_.id as id1_10_1_, teacher2_.course as course2_10_1_, teacher2_.name as name3_10_1_, teacher2_.student_relation_id as student_4_10_1_ from jei_teacher teacher0_ left outer join jei_student student1_ on teacher0_.student_relation_id=student1_.teacher_relation_id left outer join jei_teacher teacher2_ on student1_.teacher_relation_id=teacher2_.student_relation_id where teacher0_.student_relation_id=?
查询student
select student0_.id as id1_9_, student0_.address as address2_9_, student0_.name as name3_9_, student0_.teacher_relation_id as teacher_4_9_ from jei_student student0_ where student0_.id=1 and (student0_.name like ?) and (student0_.address like ?) and student0_.teacher_relation_id=100
select teacher0_.id as id1_10_2_, teacher0_.course as course2_10_2_, teacher0_.name as name3_10_2_, teacher0_.student_relation_id as student_4_10_2_, student1_.id as id1_9_0_, student1_.address as address2_9_0_, student1_.name as name3_9_0_, student1_.teacher_relation_id as teacher_4_9_0_, teacher2_.id as id1_10_1_, teacher2_.course as course2_10_1_, teacher2_.name as name3_10_1_, teacher2_.student_relation_id as student_4_10_1_ from jei_teacher teacher0_ left outer join jei_student student1_ on teacher0_.student_relation_id=student1_.teacher_relation_id left outer join jei_teacher teacher2_ on student1_.teacher_relation_id=teacher2_.student_relation_id where teacher0_.student_relation_id=?
select student0_.id as id1_9_2_, student0_.address as address2_9_2_, student0_.name as name3_9_2_, student0_.teacher_relation_id as teacher_4_9_2_, teacher1_.id as id1_10_0_, teacher1_.course as course2_10_0_, teacher1_.name as name3_10_0_, teacher1_.student_relation_id as student_4_10_0_, student2_.id as id1_9_1_, student2_.address as address2_9_1_, student2_.name as name3_9_1_, student2_.teacher_relation_id as teacher_4_9_1_ from jei_student student0_ left outer join jei_teacher teacher1_ on student0_.teacher_relation_id=teacher1_.student_relation_id left outer join jei_student student2_ on teacher1_.student_relation_id=student2_.teacher_relation_id where student0_.teacher_relation_id=?
标签:hibernate,name,映射,teacher,_.,relation,student,id,OneToOne
From: https://www.cnblogs.com/jspider/p/16815692.html