`
Qieqie
  • 浏览: 337816 次
  • 性别: Icon_minigender_1
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

一对多关系的一次有趣实践

阅读更多
不好给本贴取名,暂且看吧。

类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);
分享到:
评论

相关推荐

    自己动手写操作系统(含源代码).part2

    进而我想到,一定不只是我一个人对编写自己的操作系统怀有兴趣,也一定不只是我一个人在实践时遇到困难。或许我应该把自己的经历写下来,从而可以帮助跟我相似的后来者,就这样,我编写了本书的第一版,也就是...

    自己动手写操作系统(含源代码).part1

    进而我想到,一定不只是我一个人对编写自己的操作系统怀有兴趣,也一定不只是我一个人在实践时遇到困难。或许我应该把自己的经历写下来,从而可以帮助跟我相似的后来者,就这样,我编写了本书的第一版,也就是...

    算法导论(part1)

    我们试图使它能成为一本现在对读者有用的教材,将来在读者的职业生涯中,也能成为一本案头的数学参考书或工程实践手册。 阅读本书需要哪些预备知识呢? ·读者需要有一些程序设计方面的经验,尤其需要理解递归过程...

    算法导论(part2)

    我们试图使它能成为一本现在对读者有用的教材,将来在读者的职业生涯中,也能成为一本案头的数学参考书或工程实践手册。 阅读本书需要哪些预备知识呢? ·读者需要有一些程序设计方面的经验,尤其需要理解递归过程...

    一个进程池的服务器程序

    一个进程池的服务器程序 下面做了非常简单的http服务器,该服务器只能接收Get请求。 流程大概如下: 1,父进程listen,创建pipe(下面所有父子进程之间的通信都用该pipe) 2,父进程预fork n个子进程 3,各个子...

    C语言入门经典(第4版)--源代码及课后练习答案

     杨浩,知名译者,大学讲师,从事机械和计算机方面的教学和研究多年,发表论文数篇,参编和翻译的图书多达20余部,还曾多次获得市部级奖项。近几年一直在跟踪.NET技术的发展,积极从事.NET技术文档和图书的翻译工作...

    C#微软培训资料

    &lt;&lt;page 1&gt;&gt; page begin==================== 目 目目 目 录 录录 ... 2000 年 6 月 22 日 不论对 Microsoft 还是对整个 IT 业界都将成为值得纪念的一天 这一天 微软公司正式推出了其下一代...

    Reversing:逆向工程揭密

    第一次看到“逆向工程”这个词是在2001年的《机械工程学报》上的一篇文章中,主要是讲用三坐标测量仪测量产品中各个部件的三维尺寸并在计算机中快速建模、进而反推其设计思想和基本设计原则。第一次使用逆向工程工具...

Global site tag (gtag.js) - Google Analytics