原文: https://howtodoinjava.com/hibernate/hibernate-one-to-one-mapping-using-annotations/
如果您正在处理任何 Hiberate 项目,或者计划将来进行任何处理,那么您可以轻松了解应用中多个实体之间的一对一关系。 在此 Hibernate 一对一映射示例中,我们将讨论 Hibernate 支持的此映射的 3 种不同变体。
Table fo contentsVarious supported techniques for one to one mapping1\. Using foreign key association2\. Using common join table3\. Using shared primary key
对于此 Hiberate 一对一映射示例,我扩展了为 Hiberate HelloWorld 示例编写的示例。 这里有两个实体:Employee和Account。
一名员工可以拥有一个帐户。 同样,一个帐户将仅与一个员工关联。 在此示例中,这是一对一的关系。
各种支持的技术
在 Hiberate 下,有 3 种方法可在两个实体之间创建一对一关系。 无论哪种方式,我们都必须使用@OneToOne注解。
- 第一种技术使用最广泛,并且在其中一个表中使用外键列。
- 第二种技术使用一种众所周知的解决方案,即具有第三张表来存储前两个表之间的映射。
- 第三种技术是新技术,它在两个表中都使用了公共主键值。
1. 使用外键关联的 Hiberate 一对一映射
在这种关联中,在所有者实体中创建了一个外键列。 例如,如果我们使为EmployeeEntity为所有者,则将在Employee表中创建一个额外的列"ACCOUNT_ID"。 此列将存储Account表的外键。
表结构将如下所示:

要进行这种关联,请按如下所示引用EmployeeEntity类中的Account实体:
@OneToOne@JoinColumn(name="ACCOUNT_ID")private AccountEntity account;
连接列用@JoinColumn注解声明,看起来像 @Column 注解。 它还有一个名为referencedColumnName的参数。 此参数在目标实体中声明将用于连接的列。
如果在所有者方未声明@JoinColumn,则使用默认值。 将在所有者表中创建一个连接列,其名称将是所有者端关系名称_(下划线)和所拥有的主键列名称的连接。 侧。
在双向关系中,一方(只有一方)必须是所有者。 所有者负责关联列的更新。 为了声明对关系不负责的一方,使用了mappedBy属性。“mappedBy”是指所有者一方的关联的属性名称。
@OneToOne(mappedBy="account")private EmployeeEntity employee;
在“mappedBy”属性上方,它声明依赖于所有者实体进行映射。
让我们在运行的代码中测试上述映射:
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 objectEmployeeEntity emp = new EmployeeEntity();emp.setEmail("demo-user@mail.com");emp.setFirstName("demo");emp.setLastName("user");// Save Accountsession.saveOrUpdate(account);// Save Employeeemp.setAccount(account);session.saveOrUpdate(emp);session.getTransaction().commit();HibernateUtil.shutdown();}}
运行以上代码可在数据库中创建所需的架构,然后运行这些 SQL 查询。
Hibernate: insert into ACCOUNT (ACC_NUMBER) values (?)Hibernate: insert into Employee (ACCOUNT_ID, EMAIL, FIRST_NAME, LAST_NAME) values (?, ?, ?, ?)
当您运行上述程序时,可以在两个表中验证数据和映射。
2. 使用公共连接表的 Hiberate 一对一映射
这种方法对我们所有人都不陌生。 让我们从这种技术的目标 DB 结构开始。

在该技术中,要使用的主要注解是@JoinTable。 此注解用于定义两个表中的新表名(强制性)和外键。 让我们看看它的用法:
@OneToOne(cascade = CascadeType.ALL)@JoinTable(name="EMPLOYEE_ACCCOUNT", joinColumns = @JoinColumn(name="EMPLOYEE_ID"),inverseJoinColumns = @JoinColumn(name="ACCOUNT_ID"))private AccountEntity account;
@JoinTable注解在EmployeeEntity类中使用。 它声明将使用两列EMPLOYEE_ID(EMPLOYEE表的主键)和ACCOUNT_ID(ACCOUNT表的主键)创建一个新表EMPLOYEE_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 (?, ?)
3. 使用共享主键的 Hiberate 一对一映射
在这种技术中,Hiberate 将确保在两个表中都使用一个公共的主键值。 这样,EmployeeEntity的主键也可以安全地假定为AccountEntity的主键。
表结构将如下所示:

在这种方法中,@PrimaryKeyJoinColumn是要使用的主要注解。 让我们看看如何使用它。
@OneToOne(cascade = CascadeType.ALL)@PrimaryKeyJoinColumnprivate AccountEntity account;
在AccountEntity端,它将仍然依赖于所有者实体进行映射。
@OneToOne(mappedBy="account", cascade=CascadeType.ALL)private EmployeeEntity employee;
测试以上实体会在日志文件中生成以下 SQL 查询:
Hibernate: insert into ACCOUNT (ACC_NUMBER) values (?)Hibernate: insert into Employee (ACCOUNT_ID, EMAIL, FIRST_NAME, LAST_NAME) values (?, ?, ?, ?)
因此,我们已经看到所有 3 种不同的方式来创建 Hiberate 中支持的一对一映射。 我建议您下载源代码并使用它。
学习愉快!
