REFACTOR:清除带有多个可选参数的查询的dao代码

时间:2011-11-02 12:43:58

标签: java sql refactoring

是否有可能清理这样的dao方法? 我不喜欢每个param的2 if,但是没有类似“query.setSql()”的东西,所以我可以在添加params并构建sql之后更新sql。

public List<OriginLabel> findByCriteria(Link1 l1, Link2 l2, String att) {
    String sql = "FROM MyEntity e WHERE 1=1";
    if(l1 != null){
        sql += " AND e.link1 = :l1 ";
    }
    if(l2 != null){
        sql += " AND e.link2 = :l2 ";
    }
    if(att != null){
        sql += " AND e.attribute = :att ";
    }
    Query query = getEntityManager().createQuery(sql);
    if(l1 != null){
        query.setParameter("l1", l1);
    }
    if(l2 != null){
        query.setParameter("l2", l2);
    }
    if(att != null){
        query.setParameter("att", att);
    }
    return (List<MyEntity>)query.getResultList();
}

4 个答案:

答案 0 :(得分:1)

我将参数存储在第一个if:

中的hashmap中
public List<OriginLabel> findByCriteria(Link1 l1, Link2 l2, String att) {
    String sql = "FROM MyEntity e WHERE 1=1";
    HashMap parameters = new HashMap();
    if(l1 != null){
        sql += " AND e.link1 = :l1 ";
        parameters.put("l1", l1);
    }
    if(l2 != null){
        sql += " AND e.link2 = :l2 ";
        parameters.put("l2", l2);
    }
    if(att != null){
        sql += " AND e.attribute = :att ";
        parameters.put("att", l1);
    }
    Query query = getEntityManager().createQuery(sql);
    SQLUtility.setParameters(query, parameters);

SQLUtility.setParameters(易于实现,自行编写)循环遍历HashMap键并在query上设置参数。

答案 1 :(得分:1)

也许QueryDSL http://www.querydsl.com/可以用来改进与SQL相关的代码?

使用QueryDSL时,只使用一个if if参数构建语句(并且您的语句将在没有任何字符串杂技的情况下进行静态编译):

public List<OriginLabel> findByCriteria(Link1 l1, Link2 l2, String att) {
    QOriginLabel e = QOriginLabel.originLabel;
    JPAQuery query = new JPAQuery(em).from(e);
    if (l1 != null) {
        query.where(e.link1.eq(l1)); 
    }
    if (l2 != null) {
        query.where(e.link2.eq(l2));
    }
    if (att != null) {
        query.where(e.attribute.eq(att));
    } 
    return query.list(e);
}

答案 2 :(得分:0)

我建议调查visitor design pattrn

您可以创建访问每个参数(可访问)的访问者,同时为您的查询字符串添加条件。

答案 3 :(得分:0)

如果性能不是问题,我喜欢这样编码:

public List<OriginLabel> findByCriteria(Link1 l1, Link2 l2, String att) { 
    String sql = "FROM MyEntity e " +
            "   WHERE e.link1 = isnull(:l1, e.link1) " +
            "       AND e.link2 = isnull(:l2, e.link2)" +
            "       AND e.attribute = isnull(:att, e.attribute)"; 
    Query query = getEntityManager().createQuery(sql); 
    query.setParameter("l1", l1); 
    query.setParameter("l2", l2); 
    query.setParameter("att", att); 
    return (List<MyEntity>)query.getResultList(); 
}