问题描述
标题描述的不知所云,很难理解,实在想不出好的标题来,直接上例子了例子:学生信息管理的系统。整个系统有学生表,班级表,专业表,学院表,表字段没有冗余,即学生表只有班级编号,班级表有专业编号。现在有一个显示一个学院内所有学生的列表页,列表的每条记录除包含学生表里的字段外,还包含了班级名称,专业名称,即同一个地方要显示多张表里的信息。程序的调用流程:Action->Service->Dao这种场景在软件开发中,应该算是比较普通,想了解了大家都是如何处理的?先说下我自己的几个想法:1.学生实体类字段冗余,新增两个字段:班级名称和专业名称2.学生实体类新增班级实体对象的属性,班级实体类新增专业实体对象属性3.实体类字段不冗余,因为列表页只有一个地方,在Action里分别调用不同的Service,把页面需要显示的字段都放到Map里。4.实体类字段不冗余,引入一个StudentFacade分别调用各个Service,数据也是放到Map里。Action->Facade->Service-Dao5.实体类字段不冗余,新增一个ActionHelper,功能跟StudentFacade类似,但是它是直接把需要显示数据放置到context里1和2两点比较纠结的原因是,大部分情况下不需要班级名称和专业名称,每次获取数据的时候,都把级联信息连带取出来不太好。如果分成两个不同的方法(一个是冗余字段赋值,另一个不赋值),不仅它们方法名比较纠结,而且上层拿到Student也无法判断冗余的字段是否已经赋值。第3点是Action里整合的Service太多,若显示逻辑较多,会显得庞大,通常Action应该都是很薄的。第4点ActionHelper还是属于Action层,涉及的Service太多。本来想发到问答区,怕人气不够旺,决定发到论坛了,投新手帖没关系,但千万别沉默。 问题补充如果数据量很大,Sql跨表查询性能比较低劣!通常都是一个Dao对应一个数据表的,如果一个Dao查询多张表,也不是很合理。还有就是大部分情况下,不需要专业名称和班级名称的,是否要Dao开两个方法。
解决方案
小弟观点与你的想法有点儿不同。 1、如果数据量很大,Sql跨表查询性能比较低劣的问题!你要夸表查询说明你的此次操作设计了多张表,你的思意是只做单表查询,那就需要多次查询数据库。如果是想查多条记录就得循环查询数据库,很显然单表查询效率低的不行。我们的原则是能一次请求查询的不用 多次,一次查询的数据用程序来处理,这是我们的规范。2、dao查多张表式不可避免的,业务需求就是这样没办法。我现在用hibernate,如果要是我来做你的这个例子怎么做。你的每个表一定有个实体类吧,在你的User实体类里创建几个属性(如果班级表实体类是BanJi 专业 ZhanYe 学院XueYuan)BanJi baJi; ZhuanYe zhanYe ;XueYuan xueYuan;让后创建getter ,setter。3、在我的dao里的查询我放在你的UserDAO里 查询语句大概 from User u, BanJi b,ZhanYe z ,XueYuan x where ...; 因为hibernate查出来的就是对象列表,多表查询查出来的是对象数组列表,我解析一下。for (int i = 0; i < list.size(); i++) {Object[] o = (Object[]) list.get(i); user = new User(); banJi = new BanJi (); zhanYe = new ZhanYe(); xueYuan = new XueYuan (); user = o[0]; banJi = o[1]; zhuanYe = o[2]; xueYuan = o[3]; user.setBanJi(banJi ); user.setZhanYe(zhuanYe); user.setXueYuan(xueYuan ); //再把user放到list里返回就行了}如果你用jdbc,查出来的不是对象是数据库列,你分别放到你的对象里,然后再将那几张表的信息放到user表里,页面返回个userlist就可以了,如果有分页或其他的你在封装一下。4、“不需要专业名称和班级名称的,是否要Dao开两个方法”,个人认为没必要程序和数据库都没那么脆弱,要是像你这种想法那些关系映射的中间件就不会火啦。就像我用hibernate即使只用一张表里的一个字段有时候也把整个对象取出来。ps:以上写的如有不好兄弟别笑啊
解决方案二:
如果只是显示的话,SQL的左连接不可以么?