几种支持的技术
在Hibernate中,在两个实体间有三种方式创建one-to-one的关系,其中一种方式是使用@OneToOne注解。第一种技术广泛的被使用,在表中使用外键列;第二种技术使用众所周知的第三个表,来存储两个表间的映射关系;第三种技术是在两个表中使用普通的主键。
我们一个一个来看看
使用主键的关系
在这种关系中,外键列在自己的实体中创建,例如我们让 Employee实体作为拥有者,那么外键列ACCOUNT_ID将会在Employee表中被创建,这一列将为Account表存储外键
表的结构如下:
为了建立这种联系,在Employee实体类中如下指定account实体
-
@OneToOne
-
@JoinColumn(name="ACCOUNT_ID")
-
private AccountEntity account;
join列使用 @JoinColumn注解声明,这很像@Column注解。它有很多参数指定列名,这个参数声明了将要join的目标实体的列。如果没有@JoinColumn在拥有端进行声明的话,它是默认增加的。它的名字将会连接拥有端_(下划线)和被拥有端的主键列。在双向的关系中,一边(仅仅一边)必须要作为拥有者,拥有者负责关联列的更新。为了声明另一边不负责这个关系,可以使用mappedBy。mappedBy指的是关联的拥有者端的属性的名字
-
@OneToOne(mappedBy="account")
-
private EmployeeEntity employee;
上边的属性声明了它依赖于拥有实体的映射关系
我们来测试一下上边的映射关系
-
public class TestForeignKeyAssociation {
-
public static void main(String[] args) {
-
Session session = HibernateUtil.getSessionFactory().openSession();
-
session.beginTransaction();
-
AccountEntity account = new AccountEntity();
-
account.setAccountNumber("123-345-65454");
-
// Add new Employee object
-
EmployeeEntity emp = new EmployeeEntity();
-
emp.setEmail("demo-user@mail.com");
-
emp.setFirstName("demo");
-
emp.setLastName("user");
-
// Save Account
-
session.saveOrUpdate(account);
-
// Save Employee
-
emp.setAccount(account);
-
session.saveOrUpdate(emp);
-
session.getTransaction().commit();
-
HibernateUtil.shutdown();
-
}
-
}
运行结果:
-
Hibernate: insert into ACCOUNT (ACC_NUMBER) values (?)
-
Hibernate: insert into Employee (ACCOUNT_ID, EMAIL, FIRST_NAME, LAST_NAME) values (?, ?, ?, ?)
使用普通的连接表
这种方法对我们来说并不是新的方法,我们从它的关系表开始
在这种技术中,主要使用的标签是@JoinTable,这种标签定义新表的名字(强制性的)和两个表的外键,我们来看一下他们是怎么使用的
-
@OneToOne(cascade = CascadeType.ALL)
-
@JoinTable(name="EMPLOYEE_ACCCOUNT", joinColumns = @JoinColumn(name="EMPLOYEE_ID"),
-
inverseJoinColumns = @JoinColumn(name="ACCOUNT_ID"))
-
private AccountEntity account;
@JoinTable注解用在Employee实体类中,被声明为一个新的表EMPLOYEE_ACCOUNT将会创建两个列EMPLOYEE_ID(EMPLOYEE表的主键)和ACCOUNT_ID(ACCOUNT表的主键),测试上述的实体将会产生下边的SQL结果
-
Hibernate: insert into ACCOUNT (ACC_NUMBER) values (?)
-
Hibernate: insert into Employee (EMAIL, FIRST_NAME, LAST_NAME) values (?, ?, ?)
-
Hibernate: insert into EMPLOYEE_ACCCOUNT (ACCOUNT_ID, EMPLOYEE_ID) values (?, ?)
使用共享主键
在这种技术中,Hibernate将会确保在两个表中使用了普通的主键。这种方式Employee的实体主键可以被安全的假定为Account实体的主键
表间的结构图如下:
这种方式,主要使用的是@PrimaryKeyJoinColumn注解
-
@OneToOne(cascade = CascadeType.ALL)
-
@PrimaryKeyJoinColumn
-
private AccountEntity account;
在Account实体的那一边,依旧根据拥有者边的映射关系
-
@OneToOne(mappedBy="account", cascade=CascadeType.ALL)
-
private EmployeeEntity employee;
测试上边实体的映射关系
-
Hibernate: insert into ACCOUNT (ACC_NUMBER) values (?)
-
Hibernate: insert into Employee (ACCOUNT_ID, EMAIL, FIRST_NAME, LAST_NAME) values (?, ?, ?, ?)