这几天在改一个项目源码,遇到一个问题坑了很久。场景如下(注:此处是借鉴网络上的例子,并不是自己的实验环境): 一夫一妻制——比如夫妻关系的两张数据表,一个是wif表,一个是husban表,其数据表信息如下: CREATE TABLE `wife` ( `id` int(11) NOT NUL
这几天在改一个项目源码,遇到一个问题坑了很久。场景如下(注:此处是借鉴网络上的例子,并不是自己的实验环境):
一夫一妻制——比如夫妻关系的两张数据表,一个是wif表,一个是husban表,其数据表信息如下:
CREATE TABLE `wife` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(50) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=15 DEFAULT CHARSET=utf8 CREATE TABLE `husband` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(50) NOT NULL, `wifeid` int(11) DEFAULT NULL, PRIMARY KEY (`id`), KEY `fk_wife` (`wifeid`), CONSTRAINT `fk_wife` FOREIGN KEY (`wifeid`) REFERENCES `wife` (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=20 DEFAULT CHARSET=utf8
下面是相应的POJO:
Wife: 1. package com.linys.model; 2. 3. /** 4. * Wife entity. @author MyEclipse Persistence Tools 5. */ 6. 7. public class Wife implements java.io.Serializable { 8. 9. // Fields 10. 11. /** 12. * 13. */ 14. private static final long serialVersiOnUID= 1L; 15. private Integer id; 16. private String name; 17. private Husband husband; 18. // Constructors 19. 20. /** default constructor */ 21. public Wife() { 22. } 23. 24. /** minimal constructor */ 25. public Wife(String name) { 26. this.name = name; 27. } 28. 29. 30. // Property accessors 31. 32. public Integer getId() { 33. return this.id; 34. } 35. 36. public void setId(Integer id) { 37. this.id = id; 38. } 39. 40. public String getName() { 41. return this.name; 42. } 43. 44. public void setName(String name) { 45. this.name = name; 46. } 47. 48. public Husband getHusband() { 49. return husband; 50. } 51. 52. public void setHusband(Husband husband) { 53. this.husband = husband; 54. } 55. 56. 57. } Husband: 1. package com.linys.model; 2. 3. /** 4. * Husband entity. @author MyEclipse Persistence Tools 5. */ 6. 7. public class Husband implements java.io.Serializable { 8. 9. // Fields 10. 11. /** 12. * 13. */ 14. private static final long serialVersiOnUID= 1L; 15. private Integer id; 16. private Wife wife; 17. private String name; 18. 19. // Constructors 20. 21. /** default constructor */ 22. public Husband() { 23. } 24. 25. /** minimal constructor */ 26. public Husband(String name) { 27. this.name = name; 28. } 29. 30. /** full constructor */ 31. public Husband(Wife wife, String name) { 32. this.wife = wife; 33. this.name = name; 34. } 35. 36. // Property accessors 37. 38. public Integer getId() { 39. return this.id; 40. } 41. 42. public void setId(Integer id) { 43. this.id = id; 44. } 45. 46. public Wife getWife() { 47. return this.wife; 48. } 49. 50. public void setWife(Wife wife) { 51. this.wife = wife; 52. } 53. 54. public String getName() { 55. return this.name; 56. } 57. 58. public void setName(String name) { 59. this.name = name; 60. } 61. 62. }
一对一双向关联比较特殊,不像单向关联,在hbm配置文件中仅仅使用one-to-one配置即可,这种情况下需要使用may-to-one和one-to-one来模拟一一对应,既然是一一对应,所以在many-to-one的一段,要加上unique=true属性,从而保证其唯一性。不要问我为什么,这是Hibernate的机制吧,其实说到这里,我对于Hibernate还不是很了解,如果有大神读到希望可以指点一二。从项目经验来看,如果不这么做,在同时修改了这两个实体,然后保存到库中时,总是报错,错误信息为session无法同步,或者外键id为NULL。使用了这样的配置后,就没有问题了。下面看二者的配置文件:
Wife.hbm.xml Java代码 1. 2. 4. 7.8. Husband.hbm.xml: 1. 2. 4. 7.9. 18.10. 13.11. 12. 14. 16.15. 17. 8. 9. 20.10. 13.11. 12. 14. 16.15. 17. 18. 19.
外键所依赖的那个表的配置文件(wife)使用one-to-one,外键所在的表(husband)用many-to-one,但是要指定unique为true从而保证其唯一性。注意many这一端中的colum,配置的应该是外键所在表的外键列名,对应这里也就是husband表中的“wifeid”,需要与数据库中的数据表表中一致,切勿弄错。
one-to-one:指定在Wife这个类中用于双向关联的属性husband
property-ref: 在关联对象中用于与本对象关联的属性。
注意:property-ref="wife"不能少,否则会造成查询时关联查询失败!
以上是实际经验的总结,如有错误,欢迎指正。