构建数据库查询的设计模式

时间:2014-05-08 11:33:45

标签: java mysql sql prepared-statement

今天我正在对我的代码进行自我审查,代码对我来说并不好看(尽管它按预期工作)。所以我想要一个更好的方法来做同样的事情。 以下是这种情况:

  1. 在我的web服务中,客户端可以通过n个搜索条件对记录执行搜索操作(一个可能的标准可以是get me all the staff whose name contains A and who has designation Teacher。因此,对于这样的查询,我有许多if语句相应地进行字符串查询。但是这对我来说看起来很难看。他们是否可以使用PreparedStatement来实现这一目标。
  2. 丑陋的代码如下所示

    private String getSearchQuery(Staff staffEntity) {
        boolean hasAnySearchParam = false;
        String query = null;
        StringBuilder querybuilder = new StringBuilder("select * from " + DBConstants.StaffBasicInfo.tableName + " left outer join " + DBConstants.StaffAdvInfo.tableName + " on "
                + DBConstants.StaffBasicInfo.staffId + " = " + DBConstants.StaffAdvInfo.staff_adv_info_staffId + " where");
        if (staffEntity.getName() != null && (!staffEntity.getName().isEmpty())) {
            querybuilder.append(" " + DBConstants.StaffBasicInfo.staffname + " Like '%" + staffEntity.getName() + "%'");
            querybuilder.append(" and");
            hasAnySearchParam = true;
        }
        if (staffEntity.getDesignation() != null && (!staffEntity.getDesignation().isEmpty())) {
            querybuilder.append(" " + DBConstants.StaffBasicInfo.designation + " Like '%" + staffEntity.getDesignation() + "%'");
            querybuilder.append(" and");
            hasAnySearchParam = true;
        }
        if (staffEntity.getAge() != null) {
            querybuilder.append(" " + DBConstants.StaffBasicInfo.age + " = " + staffEntity.getAge());
            querybuilder.append(" and");
            hasAnySearchParam = true;
        }
        if (staffEntity.getUsername() != null && (!staffEntity.getUsername().isEmpty())) {
            querybuilder.append(" " + DBConstants.StaffAdvInfo.username + " Like '%" + staffEntity.getUsername() + "%'");
            querybuilder.append(" and");
            hasAnySearchParam = true;
        }
        if (staffEntity.getRole() != null && (!staffEntity.getRole().isEmpty())) {
            querybuilder.append(" " + DBConstants.StaffAdvInfo.role + " Like '%" + staffEntity.getRole() + "%'");
            querybuilder.append(" and");
            hasAnySearchParam = true;
        }
        if (false == hasAnySearchParam) {
            throw new IllegalArgumentException("Check Json: No parameter to search");
        } else {
            // need to clean query.
            query = querybuilder.substring(0, querybuilder.length() - 3);
        }
        return query;
    }
    

    注意现在我更关心代码清晰度,简单性和易用性,我可以在以后考虑性能问题。

1 个答案:

答案 0 :(得分:1)

对于这种特殊情况,我会使用带有params的静态查询,其中params是从java

设置的
WHERE
...
  and (:userNameParam is null or staffname like concat('%',:staffnameParam,'%'))
  and (:userNameParam is null or username like concat('%',:userNameParam ,'%'))
...

然后只传递参数userNameParam,userNameParam等。如果它们为null或为空则只传递null。

你的方式留下了SQL注入的可能性