找回密码
 FreeOZ用户注册
查看: 1184|回复: 0
打印 上一主题 下一主题

EJB Entity 之 One-To-One Entity关系实现及其数据表实现

[复制链接]
跳转到指定楼层
1#
发表于 27-7-2009 00:20:37 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有帐号?FreeOZ用户注册

x
实体之间有One-To-One, One-To-Many, Many-To-One, Many-To-Many的关系。
其中单单是One-To-One又可以分成unidirection, bi-direction两种。

就unidirection来看,很明显,这里可以分成主从两个实体,主实体里可以找到从实体的
对象,而从实体对于主实体可以说是一无所知的。在程序对象中,这个关系很容易表达,
只要在主实体类中结合一个从实体对象即可;而在数据库中,这种关系往往可以由
Foreign-Key来实现:Foreign-Key在哪一个表中,那么这个表就是主表,另一个表
则是从表。

但有的时候,情况是这样的:如果从表没有建立自己的独立主键,而直接使用主表的主键
作为自己的主键,这样,主表只需要在从表里查找那条包含了自己主键值的记录即可;
这种情况不需要别外附加一个新的外键。

对于上面两种情况,在EJB Entity技术中有两个对应的Annotation:
@JoinColumn
@PrimaryKeyJoinColumn

我们来看看它们是怎样实现和操作的。为了简化程序,我把两种情况在同一个Entity中实现了。

主实体
  1.   1 package persistence2;
  2.   2
  3.   3 import javax.persistence.*;
  4.   4
  5.   5 @Entity
  6.   6 @Table(name="USER")
  7.   7 public class MyUserEntity{
  8.   8     private Long id;
  9.   9     private String name;
  10. 10     private MyAddressEntity address;
  11. 11     private MyBirthdayEntity birth;
  12. 12
  13. 13     @Id
  14. 14     @GeneratedValue(strategy=GenerationType.AUTO)
  15. 15     @Column(name="USER_ID", insertable=false, updatable=false)
  16. 16     public Long getId() {
  17. 17         return id;
  18. 18     }
  19. 19
  20. 20     public void setId(Long id){
  21. 21         this.id = id;
  22. 22     }
  23. 23
  24. 24     @Column(name="USER_NAME", nullable=false, updatable=false)
  25. 25     public String getName() {
  26. 26         return name;
  27. 27     }
  28. 28
  29. 29     public void setName(String name){
  30. 30         this.name = name;
  31. 31     }
  32. 32
  33. 33     @OneToOne
  34. 34     @PrimaryKeyJoinColumn(name="USER_ID",
  35. 35         referencedColumnName="BILLING_USER_ID")
  36. 36     public MyAddressEntity getAddress() {
  37. 37         return address;
  38. 38     }
  39. 39
  40. 40     public void setAddress(MyAddressEntity address){
  41. 41         this.address = address;
  42. 42     }
  43. 43
  44. 44     @OneToOne
  45. 45     @JoinColumn(name="USER_BIRTH_ID", referencedColumnName="BIRTH_ID")
  46. 46     public MyBirthdayEntity getBirth() {
  47. 47         return birth;
  48. 48     }
  49. 49
  50. 50     public void setBirth(MyBirthdayEntity birth) {
  51. 51         this.birth = birth;
  52. 52     }
  53. 53
  54. 54 }
复制代码
使用@JoinColumn的从实体
  1.   1 package persistence2;
  2.   2
  3.   3 import javax.persistence.*;
  4.   4
  5.   5 @Entity
  6.   6 @Table(name="BIRTHDAY")
  7.   7 public class MyBirthdayEntity {
  8.   8     private Long id;
  9.   9     private java.util.Date date;
  10. 10
  11. 11     @Id
  12. 12     @GeneratedValue(strategy=GenerationType.AUTO)
  13. 13     @Column(name="BIRTH_ID")
  14. 14     public Long getId() { return id; }
  15. 15
  16. 16     public void setId(Long id) { this.id = id; }
  17. 17
  18. 18     @Column(name="BIRTH_DATE")
  19. 19     @Temporal(value=TemporalType.DATE)
  20. 20     public java.util.Date getDate() { return date; }
  21. 21
  22. 22     public void setDate(java.util.Date date) { this.date = date; }
  23. 23 }
复制代码
使用@PrimaryKeyJoinColumn的从实体
  1.   1 package persistence2;
  2.   2
  3.   3 import javax.persistence.*;
  4.   4
  5.   5 @Entity
  6.   6 @Table(name="ADDRESS")
  7.   7 public class MyAddressEntity {
  8.   8     private Long userId;
  9.   9     private String street;
  10. 10     private String suburn;
  11. 11
  12. 12     @Id
  13. 13     @Column(name="BILLING_USER_ID")
  14. 14     public Long getUserId() {
  15. 15         return userId;
  16. 16     }
  17. 17
  18. 18     public void setUserId(Long id){
  19. 19         userId = id;
  20. 20     }
  21. 21
  22. 22     @Column(name="BILLING_STREET")
  23. 23     public String getStreet()
  24. 24     {
  25. 25         return street;
  26. 26     }
  27. 27
  28. 28     public void setStreet(String street)
  29. 29     {
  30. 30         this.street = street;
  31. 31     }
  32. 32
  33. 33     @Column(name="ADDRESS_SUBURN")
  34. 34     public String getSuburn() {
  35. 35         return suburn;
  36. 36     }
  37. 37
  38. 38     public void setSuburn(String suburn){
  39. 39         this.suburn = suburn;
  40. 40     }
  41. 41
  42. 42 }
  43. 43
复制代码
操作实体的Session Bean程序(部分)
  1. 50         MyUserEntity user = new MyUserEntity();
  2. 51         MyAddressEntity address = new MyAddressEntity();
  3. 52         MyBirthdayEntity birth = new MyBirthdayEntity();
  4. 53
  5. 54         birth.setDate(new java.util.Date());
  6. 55         address.setStreet("Doomben Ave");
  7. 56         address.setSuburn("Eastwood");
  8. 57         user.setName("Key");
  9. 58         user.setAddress(address);
  10. 59         user.setBirth(birth);
  11. 60
  12. 61         manager.persist(user);
  13. 62         address.setUserId(user.getId());
  14. 63         manager.persist(address);
  15. 64         manager.persist(birth);
复制代码
这里需要注意的是程序62行,我们需要通过manager.persist(user)来materialize
user对象,然后才能获得一个id值(注意@GeneratedValue(strategy=GenerationType.AUTO))
然后再才这个id值赋给address对象。

有几种出错的可能:
1. address.userid没有赋值,这样就不能直接存放
2. address或birth两个对象之一或全部没有persist()到数据库中,程序执行不成功,
在结束这个方法的时候会抛出rollback

现在再看看数据库中的情况:

user表
  1. create table USER (USER_ID bigint generated by default as identity (start with 1), USER_NAME varchar(255) not null, USER_BIRTH_ID bigint, primary key (USER_ID))
复制代码
birthday表
  1. create table BIRTHDAY (BIRTH_ID bigint generated by default as identity (start with 1), BIRTH_DATE date, primary key (BIRTH_ID))
复制代码
address表
  1. create table ADDRESS (BILLING_USER_ID bigint not null, BILLING_STREET varchar(255), ADDRESS_SUBURN varchar(255), primary key (BILLING_USER_ID))
复制代码
user与birthday的外键
  1. alter table USER add constraint FK27E3CB1C269356 foreign key (USER_BIRTH_ID) references BIRTHDAY
复制代码
注意到,这里从user到address之间是没有外键的,他们之间采用的是primary到primary的直接关联,
换句话说,address的主键就是外键。

如果一定要建立bi-direction关系,只需要在从实体类中做手脚即可

改变后的address类
  1.   1 package persistence2;
  2.   2
  3.   3 import javax.persistence.*;
  4.   4
  5.   5 @Entity
  6.   6 @Table(name="ADDRESS")
  7.   7 public class MyAddressEntity {
  8.   8     private Long userId;
  9.   9     private String street;
  10. 10     private String suburn;
  11. 11     private MyUserEntity user;
  12. 12
  13. 13     @Id
  14. 14     @Column(name="BILLING_USER_ID")
  15. 15     public Long getUserId() {
  16. 16         return userId;
  17. 17     }
  18. 18
  19. 19     public void setUserId(Long id){
  20. 20         userId = id;
  21. 21     }
  22. 22
  23. 23     @Column(name="BILLING_STREET")
  24. 24     public String getStreet()
  25. 25     {
  26. 26         return street;
  27. 27     }
  28. 28
  29. 29     public void setStreet(String street)
  30. 30     {
  31. 31         this.street = street;
  32. 32     }
  33. 33
  34. 34     @Column(name="ADDRESS_SUBURN")
  35. 35     public String getSuburn() {
  36. 36         return suburn;
  37. 37     }
  38. 38
  39. 39     public void setSuburn(String suburn){
  40. 40         this.suburn = suburn;
  41. 41     }
  42. 42
  43. 43     @OneToOne(mappedBy="address")
  44. 44     public MyUserEntity getUser() { return user; }
  45. 45
  46. 46     public void setUser(MyUserEntity user) { this.user = user; }
  47. 47
  48. 48 }
复制代码
改变后的birthday类
  1.   1 package persistence2;
  2.   2
  3.   3 import javax.persistence.*;
  4.   4
  5.   5 @Entity
  6.   6 @Table(name="BIRTHDAY")
  7.   7 public class MyBirthdayEntity {
  8.   8     private Long id;
  9.   9     private java.util.Date date;
  10. 10     private MyUserEntity user;
  11. 11
  12. 12     @Id
  13. 13     @GeneratedValue(strategy=GenerationType.AUTO)
  14. 14     @Column(name="BIRTH_ID")
  15. 15     public Long getId() { return id; }
  16. 16
  17. 17     public void setId(Long id) { this.id = id; }
  18. 18
  19. 19     @Column(name="BIRTH_DATE")
  20. 20     @Temporal(value=TemporalType.DATE)
  21. 21     public java.util.Date getDate() { return date; }
  22. 22
  23. 23     public void setDate(java.util.Date date) { this.date = date; }
  24. 24
  25. 25     @OneToOne(mappedBy="birth")
  26. 26     public MyUserEntity getUser() { return user; }
  27. 27
  28. 28     public void setUser(MyUserEntity user) { this.user = user; }
  29. 29 }
复制代码
改变后的Session Bean
  1. 50         MyUserEntity user = new MyUserEntity();
  2. 51         MyAddressEntity address = new MyAddressEntity();
  3. 52         MyBirthdayEntity birth = new MyBirthdayEntity();
  4. 53
  5. 54         birth.setDate(new java.util.Date());
  6. 55         address.setStreet("Doomben Ave");
  7. 56         address.setSuburn("Eastwood");
  8. 57         user.setName("Key");
  9. 58         user.setAddress(address);
  10. 59         user.setBirth(birth);
  11. 60
  12. 61         birth.setUser(user);
  13. 62         address.setUser(user);
  14. 63
  15. 64         manager.persist(user);
  16. 65         address.setUserId(user.getId());
  17. 66         manager.persist(address);
  18. 67         manager.persist(birth);
复制代码
这里有一个问题:
1. mappedBy中指出的不是对应的“表字段”名称,而是类属性名称

再看一下数据库的情况,和之前是一模一样,没有改变。
可以想到,bi-direction与unidirection是程序上的概念,而不是数据库存贮的概念,
这个需要注意了。
回复  

使用道具 举报

您需要登录后才可以回帖 登录 | FreeOZ用户注册

本版积分规则

小黑屋|手机版|Archiver|FreeOZ论坛

GMT+11, 15-12-2024 15:58 , Processed in 0.012438 second(s), 17 queries , Gzip On, Redis On.

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表