前言:使用@OneToOne注解可以建立实体bean之间的一对一的关联. 一对一关联有三种情况: 一是关联的实体都共享同样的主键, 二是其中一个实体通过外键关联到另一个实体的主键 (注意要模拟一对一关联必须在外键列上添加唯一约束). 三是通过关联表来保存两个实体之间的连接关系 (注意要模拟一对一关联必须在每一个外键上添加唯一约束).
(1)共享主键来进行一对一关联映射(单向)
例子:我们用一个男人只有一个妻子为例
import javax.persistence.*;
@Entity
@Table(name = "husband")
public class Husband {
private int id;
private String name;
private Wife wife;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "id")
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@Column(name = "name")
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
//记得cascade一定要有哦要不同时保存时不会保存wife对象
@OneToOne(cascade = { CascadeType.ALL })
@PrimaryKeyJoinColumn
public Wife getWife() {
return wife;
}
public void setWife(Wife wife) {
this.wife = wife;
}
}
---------------------------
@Entity
@Table(name = "wife")
public class Wife {
private int id;
private String name;
@Id
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@Column(name = "name")
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
--------------------------
测试方法
public static void installData() {
SessionFactory sf = new AnnotationConfiguration().configure().buildSessionFactory();
Session session = sf.openSession();
Transaction tx = session.beginTransaction();
Husband husband = new Husband();
husband.setName("丁元伟");
Wife wife = new Wife();
wife.setName("不知道");
husband.setWife(wife);
session.save(husband); //只需保存husband就可以同时保存wife了
tx.commit();
/*Hibernate: 生成的sql语句
insert
into
husband
(id, name)
values
(null, ?)
Hibernate:
select
wife_.id,
wife_.name as name5_
from
wife wife_
where
wife_.id=?
Hibernate:
insert
into
wife
(name, id)
values
(?, ?)*/
}
//查询时只需查询husband就可以把wife也查出来
(2) 主键来进行一对一关联映射(双向)
Husband类不变同上
Wife类有所改变
@Entity
@Table(name = "wife")
public class Wife {
private int id;
private String name;
private Husband husband;
@Id
@GenericGenerator(name = "pkGenerator", strategy = "foreign", parameters = { @Parameter(name = "property", value = "husband") })
@GeneratedValue(generator = "pkGenerator")
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@Column(name = "name")
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@OneToOne(cascade = CascadeType.ALL, mappedBy = "wife")
@PrimaryKeyJoinColumn
public Husband getHusband() {
return husband;
}
public void setHusband(Husband husband) {
this.husband = husband;
}
}
----------------测试代码save
public static void installData() {
SessionFactory sf = new AnnotationConfiguration().configure().buildSessionFactory();
Session session = sf.openSession();
Transaction tx = session.beginTransaction();
Husband husband = new Husband();
husband.setName("丁元伟");
Wife wife = new Wife();
wife.setName("不知道");
husband.setWife(wife);//这边得写
wife.setHusband(husband); //这边也得写
session.save(husband); //只需保存husband就可以同时保存wife了
tx.commit();
}
-----------------find
public static void findDate() {
SessionFactory sf = new AnnotationConfiguration().configure().buildSessionFactory();
Session session = sf.openSession();
Transaction tx = session.beginTransaction();
/*
因为mappedBy是定义在classes中,即classes类不负责维护级联关系.即维护者是student.所以,
1.要将clsses的数据,赋给student,即用student的setClasses()方法去捆定class数据;
2.在进行数据插入/更新session.save()/session.update()时,最后操作的是student.
*/
/*Husband husband = (Husband) session.get(Husband.class, 1);
System.out.println(husband.getName());
Wife wife = husband.getWife();
System.out.println(wife.getName());*/
//上下都可行
Wife wife = (Wife) session.get(Wife.class, 1);
System.out.println(wife.getName());
Husband husband = wife.getHusband();
System.out.println(husband.getName());
tx.commit();
}
(3)一对一外键双向关联(没有中间表)
@Entity
@Table(name = "husband")
public class Husband {
private int id;
private String name;
private Wife wife;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "id")
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@Column(name = "name")
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
//记得cascade一定要有哦要不同时保存时不会保存wife对象
@OneToOne(cascade = CascadeType.ALL, mappedBy = "husband")//必须有cascade
public Wife getWife() {
return wife;
}
public void setWife(Wife wife) {
this.wife = wife;
}
}
---------------------------------------
@Entity
@Table(name = "wife")
public class Wife {
private int id;
private String name;
private Husband husband;
@Id
@Column(name = "id")
@GeneratedValue(strategy = GenerationType.AUTO)
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@Column(name = "name")
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@OneToOne(cascade = CascadeType.ALL) //必须有cascade
@JoinColumn(name = "husband_id")
public Husband getHusband() {
return husband;
}
public void setHusband(Husband husband) {
this.husband = husband;
}
}
---------------------------------------
public static void installData() {
SessionFactory sf = new AnnotationConfiguration().configure().buildSessionFactory();
Session session = sf.openSession();
Transaction tx = session.beginTransaction();
tx.begin();
Husband husband = new Husband();
husband.setName("张三");
Wife wife = new Wife();
wife.setName("如花");
wife.setHusband(husband);
husband.setWife(wife);
session.save(husband);
//或session.save(wife); 但双方得相互设入对方
tx.commit();
}
-------------------------------------
下面查询时如果只查一方都会带出另一方内容(left outer join关联所以得设置为延迟加载)
/*
因为mappedBy是定义在classes中,即classes类不负责维护级联关系.即维护者是student.所以,
1.要将clsses的数据,赋给student,即用student的setClasses()方法去捆定class数据;
2.在进行数据插入/更新session.save()/session.update()时,最后操作的是student.
*/
Husband husband = (Husband) session.get(Husband.class, 1);
System.out.println(husband.getName());
Wife wife = husband.getWife();
System.out.println(wife.getName());
//上下都可行
/*Wife wife = (Wife) session.get(Wife.class, 1);
System.out.println(wife.getName());
Husband husband = wife.getHusband();
System.out.println(husband.getName());*/
4)一对一外键单向关联(没有中间表)
单向关联就是一边不设关联
//这边没有设置关联操作其他的和上面3的一样
@Entity
@Table(name = "husband")
public class Husband {
private int id;
private String name;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "id")
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@Column(name = "name")
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
(5)hibernate 注解一对一关系 关联表关联
请参考
http://gyfbao.blog.sohu.com/166353836.html
测试关联表时如出现下面这个错,需先主键类持久化或保存相对应的另一个非主键类
org.hibernate.PropertyValueException: not-null property references a null or transient value: