Java Spring开发一次性将对象的所有子对象从数据库中拉取出来是否合理?
比如:
有一个Company公司类,
Company公司类中有一个List<User>用户列表,
User类中有一个Address类用于存放用户的若干地址。
那么,现在有这样一种系统设计思路:
传一个公司id给后端,则在后端直接构造出该公司实例以及其下所有用户对象以及各个用户对象下的所有地址信息。
最后生成的对象就像这样:
Company{
User{
Address{}
Address{}
}
User{
Address{}
}
User{
Address{}
Address{}
Address{}
}
}
这样设计有一个好处是你要使用的时候可以直接Company.User[i].Address[j]来调用你想用的信息。但是在构造它的时候会耗费大量的数据库查询性能并且可能存在数据不同步问题。
想问下大家,这种系统设计思路,是否合理?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
你好,我最近在写一个java的orm框架,刚好也涉及到这方面的问题。我在之前设计的时候,也是考虑的获取数据库数据时一次性全部获取出来,但我设计的时候遇到的如下问题:
1. 代码复杂
考虑如下对象:
在映射关系上,one-one映射和one-many映射比较好处理,但是如果有类似这样多个映射关系 Province-->City-->Country 而且又包含集合的时候,保存时在设计上是非常复杂的.我有查看过nutzDAO的文档,它的实现方式其实是将数组中的对象压入队列中作为单个对象插入,然而毫无疑问,如果插入大量数据,这样的性能肯定很底下.我在设计orm框架时就是觉得对于复杂的映射关系,不仅代码复杂而且性能很难保证,所以决定弃用这种一次取出来和一次性保存的方式。
所以我最后设计的思想如下代码:
将外键仅仅当作普通的成员变量,在查询时将外键作为条件查询即可.保存时,先保存Province变量,获取到id后,再插入City变量,设置他们的proviceId为获取到的id即可.简化设计也提高性能.
2. 性能
诚如你的问题所说,实际上很多时候我们并不需要提取相关的所有数据,在性能和代码复杂性做平衡考虑,实际上查询数据时,单个表查询,逻辑最清楚,程序员开发时也不容易出错,可以根据自己的需要做定制.特别是对于企业项目,多个实体互相关联,如果一次性提取出来,可能数据量比较庞大,而程序员获取只需要其中的一小部分数据,这样在性能上得不偿失.
总结
总结一下我的答案就是,为了简单和性能着想,一次性取出所有数据(一次性保存实体所有相关实体数据)增加代码复杂性又增加了性能负担。
另外本人最近参考了市面的一些orm框架,自己编写了一款还处于快照期(API不稳定)的Java开源ORM框架,限于社区规范,如果感兴趣的可以私信本人交流哦。
另外再多提一嘴,本人最近看了国内的几个技术相关的社区,感觉很多社区技术氛围不是很好,披着程序员交流,技术交流的皮,但是几乎都是各种灌水,交流,征婚,文风跟贴吧简直没有区别. 更让我觉得有些气愤又有一些羞耻的是,有一些中国"开发者"在github上开源项目的的外国人(我不知道有没有针对中国开发者github项目)的issue区发一些毫无意义的灌水帖,而且评论有十几楼,完全中国式的文风(例如有人评论"six,six,six","Please sit down, Mr. Chen","double click! six six six"),虽然底下也有几位中国开发者为这样的行为道歉,但看了这样的行为,同作为国人,还是感觉到气氛和羞耻的.
关注到segmentFault是刚好最近看到有一篇主题帖,讲的就是因为用户量增加,为了规范回答,会提出更加严格的提问规范.我知道对于在用户量和技术氛围上做平衡其实是一件很难的事情(根据比例原则,除非中国人的整体素质大幅提升),因此非常希望segmentFault的管理团队能够尽力维持好整个社区的技术氛围,我也决定将扎根segmentFault社区,回答一些我力所能及的问题.
如果这些数据都需要用到,可以全部加载出来。否则就按需加载,用到的时候再加载。
数据量不大的情况下可以这么做
题主这么存储想用来解决什么业务,Company.User[i].Address[j]这种方式,感觉也就是用来便利,并没有节省查询的效率呀,单纯是为了便利列表的话,除非需求很频繁,能节省构建。其他情况,没看出什么效率上的优势。
这样的数据结构只是一个外部的接口,后端不一定是一次性全都从数据库里读出来,还可以使用懒加载的方式,具体懒到什么程度还可以调整