hibernate 自然键 和 复合自然键

必须提醒你:当应用程序继承现有的遗留数据库Schema时,通常应该尽可能地对现有的Schema少做一些改变。你
对Schema所做的每一处改变都可能破坏访问数据库的其他现有应用程序。现有数据的迁移可能很昂贵,这也是你要考虑
的问题。一般来说,构建一个新的应用程序不可能不对现有的数据模型做任何改变--新应用程序通常意味着
额外的业务需求,自然需要数据库Schema的演变。




处理主键:
不幸的是,遗留的数据库很多使用了自然主键、复合键,这样在业务需求改变时,很难重构数据库。


1、映射自然键
如你遇到的User表,可能userName是一个自燃键。那么你就需要告诉hibernate,标示符是在对象保存之前由应用
分配的一个自燃键:
  1. <classname="User"table="USER">
  2. <!-- PRIMARY KEY(`USER_NAME`) -->
  3. <id name="userName"column="USER_NAME">
  4. <generatorclass="assigned"></generator>
  5. </id>
  6. <property name="password"></property>
  7. </class>

JPA实现:
  1. @Entity
  2. publicclassUserimplementsSerializable {
  3. @Id
  4. @Column(name="USER_NAME")
  5. privateString userName;
  6. privateString password;


2、映射复合自然健
复合主键单独抽取出来一个实体来表示主键会比较优雅
代码:
UserID:要重装hashCode
  1. publicclassUserIdimplementsSerializable {
  2. privateString userCode;
  3. privateString userName;
  4. publicUserId() {
  5. super();
  6. }
  7. publicUserId(String userCode, String userName) {
  8. super();
  9. this.userCode = userCode;
  10. this.userName = userName;
  11. }
  12. publicString getUserCode() {
  13. returnuserCode;
  14. }
  15. publicvoidsetUserCode(String userCode) {
  16. this.userCode = userCode;
  17. }
  18. publicString getUserName() {
  19. returnuserName;
  20. }
  21. publicvoidsetUserName(String userName) {
  22. this.userName = userName;
  23. }
  24. @Override
  25. publicinthashCode() {
  26. finalintprime =31;
  27. intresult =1;
  28. result = prime * result
  29. + ((userCode ==null) ?0: userCode.hashCode());
  30. result = prime * result
  31. + ((userName ==null) ?0: userName.hashCode());
  32. returnresult;
  33. }
  34. @Override
  35. publicbooleanequals(Object obj) {
  36. if(this== obj)
  37. returntrue;
  38. if(obj ==null)
  39. returnfalse;
  40. if(getClass() != obj.getClass())
  41. returnfalse;
  42. UserId other = (UserId) obj;
  43. if(userCode ==null) {
  44. if(other.userCode !=null)
  45. returnfalse;
  46. }elseif(!userCode.equals(other.userCode))
  47. returnfalse;
  48. if(userName ==null) {
  49. if(other.userName !=null)
  50. returnfalse;
  51. }elseif(!userName.equals(other.userName))
  52. returnfalse;
  53. returntrue;
  54. }
  55. @Override
  56. publicString toString() {
  57. return"UserId [userCode="+ userCode +", userName="+ userName +"]";
  58. }
  59. }

User:
  1. publicclassUserimplementsSerializable {
  2. privateUserId userId;
  3. privateString password;

查询比较特别:
  1. UserId userId =newUserId("code","hello");
  2. User user = (User) session.get(User.class, userId);


3、复合主键中的外键/4、复合主键的外键
代码:
  1. publicclassUserimplementsSerializable {
  2. privateUserId userId;
  3. privateString password;
  4. privateDepartment department;
  5. privateSet<Item> items =newHashSet<Item>();
  1. publicclassDepartmentimplementsSerializable {
  2. privateInteger departmentId;
  3. privateString departmentName;
  4. privateSet<User> users =newHashSet<User>();
  1. publicclassItemimplementsSerializable {
  2. privateInteger itemId;
  3. privateString itemName;
  4. privateUser user;

配置文件:
  1. <classname="User"table="USER">
  2. <composite-id name="userId"class="UserId">
  3. <key-property name="userCode"column="USER_CODE"></key-property>
  4. <key-property name="userName"column="USER_NAME"></key-property>
  5. </composite-id>
  6. <property name="password"></property>
  7. <many-to-one name="department"class="Department"
  8. column="DEPARTMENT_ID"
  9. cascade="save-update"></many-to-one>
  10. <set name="items"cascade="save-update"inverse="true">
  11. <key>
  12. <column name="USER_CODE"></column>
  13. <column name="USER_NAME"></column>
  14. </key>
  15. <one-to-manyclass="Item"/>
  16. </set>
  17. </class>
  1. <classname="Department"table="Department">
  2. <id name="departmentId"column="DEPARTMENT_ID">
  3. <generatorclass="native"></generator>
  4. </id>
  5. <property name="departmentName"column="department_Name"></property>
  6. <set name="users"inverse="true"cascade="save-update">
  7. <key column="DEPARTMENT_ID"></key>
  8. <one-to-manyclass="User"/>
  9. </set>
  10. </class>
  1. <classname="Item"table="Item">
  2. <id name="itemId"column="item_Id">
  3. <generatorclass="native"></generator>
  4. </id>
  5. <property name="itemName"column="item_Name"></property>
  6. <many-to-one name="user"class="User">
  7. <column name="USER_CODE"></column>
  8. <column name="USER_NAME"></column>
  9. </many-to-one>
  10. </class>

插入:
  1. User user =newUser("123");
  2. UserId userId =newUserId("code","hello");
  3. user.setUserId(userId);
  4. Department department =newDepartment("de hello");
  5. user.setDepartment(department);
  6. Item item =newItem("item1");
  7. user.getItems().add(item);
  8. //必须添加,因为,在<set name="items" cascade="save-update" inverse="true">设置了反向控制,
  9. //那么就由Item的user属性来控制之间的关系,所以Item的user必须知道user的存在
  10. //要知道这个东西和cascade="save-update"并不想干,cascade只是负责是否级联保存的,和表之间的关系由谁维护无关(这一点相信很多人都会搞混)
  11. item.setUser(user);
  12. session.save(user);

5、利用注解的复合键
  1. @Embeddable
  2. publicclassUserIdimplementsSerializable {
  3. privateString userCode;
  4. privateString userName;
  1. @Entity
  2. publicclassUserimplementsSerializable {
  3. @Id
  4. @AttributeOverrides({
  5. @AttributeOverride(name="userCode",
  6. column=@Column(name="user_Code")),
  7. @AttributeOverride(name="userName",
  8. column=@Column(name="user_Name"))
  9. })
  10. privateUserId userId;
  11. privateString password;
  12. @OneToMany(mappedBy="user")
  13. privateSet<Item> items =newHashSet<Item>();
  1. @Entity
  2. publicclassItemimplementsSerializable {
  3. @Id
  4. @GeneratedValue
  5. @Column(name="ITEM_ID")
  6. privateInteger itemId;
  7. privateString itemName;
  8. //KEY `FK22EF338367E49C` (`user_Code`,`user_Name`),
  9. //CONSTRAINT `FK22EF338367E49C` FOREIGN KEY (`user_Code`, `user_Name`) REFERENCES `user` (`user_Code`, `user_Name`)
  10. @ManyToOne
  11. @JoinColumns({
  12. @JoinColumn(name="user_Code"),
  13. @JoinColumn(name="user_Name")
  14. })
  15. privateUser user;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值