将设计模式应用到日常的 curd 中—分离关联查询
看一个例子:在我们给客户端提供的接口中,有一个是要查询用户发布动态的列表。那么在接口的返回值中就需要包含 userName、*headPhoto* 这两个属性。一种做法是: 通过写一条关联查询(动态表和用户表)的sql语句,一次性返回客户端用到的所有信息。
关联查询带来的问题
数据库表之间的耦合
这个问题要具体场景具体分析。如果两张表处在不同的业务范围,那么就可能造成不同业务之间的耦合。如果在同一个业务范围内,则可以直接连表查询。其实在单体应用中也应该注重业务领域的划分。
代码复用度和复杂度
如果后续又有n个这种类型的接口,那么按照上面的做法,在每一个sql语句中都需要写一次关联用户表的sql语句。再或者查询用户信息的逻辑比较复杂,那这种复杂度势必会引入到不同的业务逻辑里。
性能的考虑
如果一条sql语句写的沉长复杂,就会难以维护又容易引发数据库性能问题
sql语句的分离
基于上面因素的考虑,我更倾向于第二种查询方式:
使用两条单独的查询语句,将查询到的结果放到代码中做数据组装。
这么做虽说开始麻烦一点,但却是好处多多。别小看这一简单的分离,却能够解决上面提到的三个问题。按照这种思路讲一下如何实现:
具体实现(Setter接口)
先来定义一个接口
这个接口是为我们的实体类定义的。所有需要显示用户名和头像的实体类都可以实现此接口
其实这里也可以定义一个父类,然后让子类去继承这个类。只不过当时在我们项目中已经有多个类需要返回用户信息,但是在不同的类中命名却不统一,重构时又不能改变属性命名。所以只能用接口做适配了
此接口的目的就是要让赋值用户信息的操作变得更通用化。
修改实体类
现在有一个用于表示动态列表数据的实体类,然后需要实现SetUserBaseInfoInterface接口
注意到在Info中的属性的命名和接口中定义的方法名并不匹配,如果统一的话,其实只有加一个 @Data 注解就不需要去手写 SetUserBaseInfoInterface 接口的实现了
赋值操作
再看如何给实体赋值,我们可以在UserService中定义一个方法:如下
有了这个方法,以后任何想要显示用户信息的实体都可以实现 SetUserBaseInfoInterface 接口 然后调用 UserService.setUserBaseInfo 方法来设置属性值。所以业务代码大概可以这么写:
从此以后,只要涉及到查询用户名和头像的地方,都可以使用上面的代码,而不需要在xml中写既无聊有蹩脚的sql语句了。可以给它起个名字叫做: Setter接口。在不同的业务中,可以定义很多Setter接口。
版权声明: 本文为 InfoQ 作者【LSJ】的原创文章。
原文链接:【http://xie.infoq.cn/article/7553c8520d2f1795bbeeceba8】。文章转载请联系作者。
评论 (1 条评论)