【Hibernate】Hibernate实体关系映射——主键相同的一对一关系

阳光穿透心脏的1/2处 2022-08-01 06:07 279阅读 0赞

主键相同的一对一关系

由于两个实体类是一对一的关系,因此可设置两个实体类使用相同的主键。反过来,具有相同主键的实体被视为一对一的关系。这样两个表就省掉了外键关联。

以客户地址管理为例学习主键相同的一对一关系:一个客户对应一个地址,对应的实体之间使用相同的主键。

客户与地址之间是一对一的关系,并且两个实体的id是相同的。双方都有对方的引用。注意,两个数据库表之间没有关联关系,hibernate是根据主键判断对应关系的。

Customer客户实体类中有一个id主键、一个name属性以及一个Address地址属性。其中Address地址属性与Customer客户实体类之间是一对一的属性,两者之间使用相同的主键,而没有使用传统的外键约束。用@OneToOne指定Address属性为一对一的,用@PrimaryKeyJoinColumn制定两个实体使用相同的主键

Customer.java

  1. package com.lmb.hibernate.bean;
  2. import javax.persistence.Entity;
  3. import javax.persistence.GeneratedValue;
  4. import javax.persistence.GenerationType;
  5. import javax.persistence.Id;
  6. import javax.persistence.OneToOne;
  7. import javax.persistence.PrimaryKeyJoinColumn;
  8. import javax.persistence.Table;
  9. @Entity
  10. @Table(name="tb_customer")
  11. public class Customer {
  12. @Id
  13. @GeneratedValue(strategy=GenerationType.AUTO) //使用主键生成策略来生成id
  14. private Integer id;
  15. private String name;
  16. @OneToOne
  17. @PrimaryKeyJoinColumn //一对一实体的主键相同
  18. private Address address;
  19. public Integer getId() {
  20. return id;
  21. }
  22. public void setId(Integer id) {
  23. this.id = id;
  24. }
  25. public String getName() {
  26. return name;
  27. }
  28. public void setName(String name) {
  29. this.name = name;
  30. }
  31. public Address getAddress() {
  32. return address;
  33. }
  34. public void setAddress(Address address) {
  35. this.address = address;
  36. }
  37. }

Adderss地址实体类具有id主键、Customer客户属性、Adderss地址、zip邮编以及telephone电话号码等3个普通属性。Id主键使用@Id标注,因为实体间使用相同的id,因此不能使用任何的主键生成策略。Customer属性上用@OneToOne指定为一对一属性,并用@PrimaryKeyJoinColumn声明使用相同主键。

Address.java

  1. package com.lmb.hibernate.bean;
  2. import javax.persistence.Entity;
  3. import javax.persistence.Id;
  4. import javax.persistence.OneToOne;
  5. import javax.persistence.PrimaryKeyJoinColumn;
  6. import javax.persistence.Table;
  7. @Entity
  8. @Table(name="tb_address")
  9. public class Address {
  10. @Id
  11. // @GeneratedValue(strategy=GenerationType.AUTO) //不能使用数据库自动分配ID
  12. private Integer id;
  13. @OneToOne
  14. @PrimaryKeyJoinColumn
  15. private Customer customer;
  16. private String address;
  17. private String zip;
  18. private String telephone;
  19. public Integer getId() {
  20. return id;
  21. }
  22. public void setId(Integer id) {
  23. this.id = id;
  24. }
  25. public Customer getCustomer() {
  26. return customer;
  27. }
  28. public void setCustomer(Customer customer) {
  29. this.customer = customer;
  30. }
  31. public String getAddress() {
  32. return address;
  33. }
  34. public void setAddress(String address) {
  35. this.address = address;
  36. }
  37. public String getZip() {
  38. return zip;
  39. }
  40. public void setZip(String zip) {
  41. this.zip = zip;
  42. }
  43. public String getTelephone() {
  44. return telephone;
  45. }
  46. public void setTelephone(String telephone) {
  47. this.telephone = telephone;
  48. }
  49. }

测试方法:

不能使用数据库自动分配ID,自动分配的ID可能会是两个实体对象ID不一致。hibernate也不会自动保证两个实体ID相同,这时候要手工设置ID保证两个实体ID一致。测试代码如下:

TestCustomerAddress.java

  1. package com.lmb.hibernate.test;
  2. import org.hibernate.Session;
  3. import com.lmb.hibernate.HibernateSessionFactory;
  4. import com.lmb.hibernate.bean.Address;
  5. import com.lmb.hibernate.bean.Customer;
  6. public class TestCustomerAddress {
  7. public static void main(String[] args) {
  8. //先实例化一个Customer对象
  9. Customer customer=new Customer();
  10. customer.setName("lmb");
  11. //实例化一个Address对象
  12. Address address=new Address();
  13. address.setAddress("湖北省武汉市");
  14. address.setTelephone("15802749021");
  15. address.setZip("430023");
  16. // address.setCustomer(customer);//注意:这里不设置关系
  17. Session session=HibernateSessionFactory.getSession();
  18. session.beginTransaction();//开启事务
  19. session.persist(customer);//将Customer对象持久化到数据库,数据库会为customer自动分配ID
  20. //要手工设置address的ID,保证两个ID一致
  21. address.setId(customer.getId());
  22. session.persist(address);//将Address对象持久化到数据库
  23. session.flush();
  24. //之后从数据库中查询Customer对象...代码略...
  25. }
  26. }

注意:

程序中没有设置Address和Customer间的关系,但是查询Customer时仍能获取到对象的Address对象。因为hibernate会自动加载相同主键的另一边的对象。

发表评论

表情:
评论列表 (有 0 条评论,279人围观)

还没有评论,来说两句吧...

相关阅读