J2EE应用下基于AOP的抓取策略实现 - 编程入门网
J2EE应用下基于AOP的抓取策略实现时间:2009-10-10 infoq Manjunath R Na使用了O/R Mapping工具的典型J2EE应用都会面临这样一个问题:如何通过最精简的SQL查询获取所需的数据。很多时候这可不是轻而易举的事情。默认情况下,O/R Mapping工具会按需加载数据,除非你改变了其默认设置。延迟加载行为保证了依赖的数据只有在真正请求时才会被加载进来,这样就可以避免创建无谓的对象。有时我们的业务并不会使用到依赖的那些组件,这时延迟加载就派上用场了,同时也无需加载那些用不上的组件了。 典型情况下,我们的业务很清楚需要哪些数据。但由于使用了延迟加载,在执行大量Select查询时数据库的性能会降低,因为业务所需的数据并不是一下子获得的。这样,对于那些需要支持大量请求的应用来说可能会产生瓶颈(可伸缩性问题)。 来看个例子吧,假设某个业务流程想要得到一个Person及其Address信息。我们将Address组件配置成延迟加载,这样要想得到所需的数据就需要更多的SQL查询,也就是说首先查询Person,然后再查询Address。这增加了数据库与应用之间的通信成本。解决办法就是在一个单独的查询中将 Person和Address都得到,因为我们知道这两个组件都是业务流程所需的。 如果在DAO/Repository及底层Service开发特定于业务的Fetching-API,对于那些拥有不同数据集的相同领域对象来说,我们就得编写不同的API进行抓取并组装了。这么做会使Repository及底层Service过于膨胀,最终变成维护的梦魇。 延迟抓取的另一个问题就是在获取到请求的数据前要一直打开数据库连接,否则应用就会抛出一个延迟加载异常。 说明:如果在查询中使用预先抓取来获取二级缓存中的数据时,我们将无法解决上面提出的问题。对于Hibernate来说,如果我们使用预先抓取来获取二级缓存中的数据,那么它将从数据库而不是缓存中去获取数据,哪怕是二级缓存中已经存在该数据。这就说明Hibernate也没有解决这个问题,从而表明我们不应该在查询中通过预先抓取来获得二级缓存中的对象。 对于那些可以让我们调节查询以获取缓存对象的O/R Mapping工具来说,如果缓存中有对象就会从缓存中获取,否则采取预先抓取的方式。这就解决了上面提到的事务/DB连接问题,因为在查询的执行过程中会同时获取缓存中的数据而不是按需读取(也就是延迟加载)。 通过下面的示例代码来了解一下延迟加载所面对的问题及解决办法。考虑如下场景:某领域中有3个实体,分别是Employee、Department及Dependent。 这三个实体之间的关系如下: Employee有0或多个dependents。 Department有0或多个employees。 Employee属于0或1个department。 我们要执行三个操作: 获取employee的详细信息。 获取employee及其dependent的详细信息。 获取employee及其department的详细信息。 J2EE应用下基于AOP的抓取策略实现(2)时间:2009-10-10 infoq Manjunath R Na以上三个操作需要获取并呈现不同的数据。使用延迟加载有如下弊端: 如果对实体employee所关联的dependent和department这两个实体使用延迟加载,那么在操作2和3中就会生成更多的SQL查询语句。 在多个查询语句的执行过程中需要保持数据库连接,否则会抛出一个延迟加载异常,这将导致数据出现问题。 但另一方面,使用预先抓取也存在如下弊端: 对employee所对应的dependents和department采取预先抓取会产生不必要的数据。 无法在特定的场景下对查询进行调优。 在Repository/DAO或底层服务中使用特定于操作的API可以解决上述问题,但却会导致如下问题: 代码膨胀——不管是Service还是Repository/DAO类都无法幸免。 维护的梦魇——不管是Service还是Repository/DAO层,只要有新的操作都需要增加新 |
凌众科技专业提供服务器租用、服务器托管、企业邮局、虚拟主机等服务,公司网站:http://www.lingzhong.cn 为了给广大客户了解更多的技术信息,本技术文章收集来源于网络,凌众科技尊重文章作者的版权,如果有涉及你的版权有必要删除你的文章,请和我们联系。以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢! |