我有一个REST API,它将根据特定的搜索条件提供搜索结果。 用户可以使用部门ID,用户ID和加入日期进行搜索。 所以在这里,用户可以搜索7种不同的组合。
根据我们的应用程序的当前设计,对于每个标准,我将不得不以不同的顺序调用不同的服务以获取信息。
例如:我们有一个包含用户详细信息的现有用户服务,一个包含详细信息的部门服务。因此,如果用户只搜索用户ID,我会直接转到UserService。如果用户使用部门ID&用户我首先要查询Dept服务,然后查询用户服务。
我目前的代码是:
if(Util.hasOnlyUserId(searchCriteria)) {
searchResponse = searchWithUserId(searchRequest);
} else if(Util.hasOnlyJoinedDate(searchCriteria)) {
searchResponse = searchWithDate(searchRequest);
} else if (Util.hasOnlyDeptID(searchCriteria)) {
searchResponse = searchWithDeptId(searchRequest);
} else if (Util.hasUserIdAndDeptId(searchCriteria)) {
searchResponse = searchWithUserIdAndDeptId(searchRequest);
} else if (Util.hasUserIdAndDate(searchCriteria)){
searchResponse = searchWithUserIdAndDate(searchRequest);
} else if (Util.hasDeptIdAndDate(searchCriteria)) {
searchResponse = searchWithDeptIdAndDate(searchRequest);
} else if (Util.hasAllCriteria(searchCriteria)) {
searchResponse = searchWithAllCriteria(searchRequest);
}
这里,searchCriteria是我的请求对象(POJO),它将这些搜索元素作为私有成员。
searchResponse这里是一种SearchResponse对象,它是API的实际响应,它包含用户的详细信息,如name,id,position,lastSalaryDrawn,CommuteType,MaritalStatus和Last Promoted Date
我一直试图优化这个多个if-else条件换句话说,避免出现这种多重条件。 我试图将它们分开并将它们分成不同的方法。但这并不令我满意,似乎它处于一种不可优化的状态。
关于如何做到这一点的任何想法将不胜感激。
编辑:我们正在使用JPA与MySQL进行交互。 这里的问题是我不会直接从DB获取信息。因此,构建动态查询可能不起作用。 需要从多个微服务中获取信息,这些服务将调用其本机数据库并将所需信息作为响应发送。 我希望这是有道理的。
答案 0 :(得分:1)
您可以将代码移动到执行条件的位置并动态构建查询:
public SearchResponse searchWithCriteria(Criteria searchCriteria) {
StringBuilder query = new StringBuilder("SELECT * FROM ... WHERE ...");
if (util.hasUserId(searchCriteria))
query.append(" AND userId = :userId");
if (util.hasJoinedDate(searchCriteria))
query.append(" AND joinedDate = :joinedDate");
...
PreparedStatement stmt = connection.prepareStatement(query);
if (util.hasUserId(searchCriteria))
stmt.setString("userId", searchCriteria.getUserId());
if (util.hasJoinedDate(searchCriteria))
stmt.setDate("joinedDate", searchCriteria.getJoinedDate());
...
ResultSet res = stmt.executeQuery();
...
}
答案 1 :(得分:0)
可以使用Strategy pattern优化代码。
答案 2 :(得分:0)
此处可以使用各种模式,您必须根据搜索代码的外观选择一种模式。有些人已经提到了战略和责任链模式。您可以看到的另一个是Builder模式。它允许您拥有仅在需要时指定的可选部件,以构建最终对象。
因此,当您添加更多的过滤条件时,您可以拥有一个SearchBuilder
类来更新有关搜索的信息。它可能包含setUserId(...)
,setDeptId(...)
等方法。
例如:如果将搜索转换为PreparedStatement
中的纯SQL查询,则只要设置了其中一个过滤字段,构建器就会存储它们(它们将以null
开头) 。因此,如果在构建器中调用了setUserId()和setDeptId(),那么构建器中的那些将不是null
,并且您生成一个带有字符串的查询(为您想要的每个额外字段附加AND ...
过滤器):
select * from users where id=? AND dept_id=?
SearchBuilder
可以提供build()
方法,然后返回一个携带查询的Search
对象,甚至可以提供执行查询的方法,或者您需要做的任何事情。