浏览 1857 次
锁定老帖子 主题:一对多关系的一次有趣实践
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2007-11-10
类A 和 类B 具有一对多的关系。A有子类 A1 和 A2,且A1和A2的字段个数和种类相差较大。 系统对A的检索/查找要求较低,对B的检索/查找功能较多也较重要。 表设计如下: A采用TABLE_PER_CLASS的方式,即A1和A2各一张表TABLE_A1, TABLE_A2。 (系统不会有同时列出A1和A2的查询,也可以容忍A1和A2可重复一个ID) 类B映射为一个表TABLE_B,并设置了一个外键A_ID,关联对B的关系。 OK!现在如何让系统知道A_ID对应的是TABLE_A1,还是TABLE_A2? 习惯从数据库角度看问题的,可以这样解决: 在TABLE_B中增加一个字段type,当type="A1"时,外键A_ID代表关联到TABLE_A1表。当="A2"时,外键A_ID代表关联到TABLE_A2表。 (其它方式的,比如规定A1主键和A2主键进行规则区分等等方案暂不考虑) 但如何在Hibernate配置这种关系?翻了Hibernate的参考手册可没直接这方面的资料。 好在B在现实中也确实存在分类的问题,那就这样吧: @Entity @Inheritance(strategy = InheritanceType.SINGLE_TABLE) @DiscriminatorColumn(name = "type") public abstract class B { // ...省略主键以及其他属性的 protected A a; @Entity @DiscriminatorValue(value = "A1") public static class B1 extends B { @Override @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "A_ID") public A1 getA() { return (A1) a; } } @Entity @DiscriminatorValue(value = "A2") public static class B2 extends B { @Override @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "A_ID") public A2 getA() { return (A2) a; } } //这里需要配置Transient,子类需override本方法负责具体映射 @Transient public A getA() { return a; } public void setA(A a) { this.a = a; } } 配置文件大概是这样的(关键是要把B$B1, B$B2, A1, A2列进去,而A基本可以不列进去): <mapping class="com.yourapp.domain.B" /> <mapping class="com.yourapp.domain.B$B1" /> <mapping class="com.yourapp.domain.B$B2" /> <mapping class="com.yourapp.domain.A1" /> <mapping class="com.yourapp.domain.A2" /> 经实践,这种方式用起来很顺畅,能够通过以下测试(测试期间一个事务保持Sesison不会被关闭): B b1 = bDao.loadById(某实际是B.B1类的纪录ID); assertEquals(B.B1.class, b1.getClass()); B b2 = bDao.loadById(某实际是B.B2类的纪录ID); assertEquals(B.B2.class, b2.getClass()); A a1 = b1.getA(); assertNotEquals(A1.class, a1.getClass());//Lazy的缘故导致不等 assertTrue(a1 instanceof A1); A a2 = b2.getA(); assertNotEquals(A2.class, a2.getClass()); assertTrue(a2 instanceof A2); 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |