【问题标题】:Building a string with comma separated values使用逗号分隔值构建字符串
【发布时间】:2012-05-22 23:10:34
【问题描述】:

为了构建数据库系统,我使用一个简单的构建器来生成基于用户选择的选择查询。它有几个布尔值,然后按如下方式进行

    StringBuilder builder = new StringBuilder();
    builder.append("SELECT ");
    if(addOpen)
        builder.append("Open ");
    if(addHigh)
        builder.append("High ");
    if(addLow)
        builder.append("Low ");
    if(addSettle)
        builder.append("Settle ");
    builder.append("FROM " + tableName);

现在,我的问题是微不足道的 - 我需要包含逗号,但如果我包含逗号,则后面必须有一个值,所以我不能执行 Open、Open、Close 等操作。是否有一个巧妙的解决方案微不足道,但对我来说却非常困难的问题?

【问题讨论】:

    标签: java sql string stringbuilder


    【解决方案1】:

    您是否正在寻找类似Apache Commons' StringUtils.join() 的方法?即:

    Collection<String> selections = Arrays.asList("Open", "Low");
    String clause = StringUtils.join(selections, ',');
    

    那么就

    String sql = "SELECT " + clause + " FROM " + TableName;
    

    【讨论】:

      【解决方案2】:

      1) 典型情况是您先验地知道您拥有多少物品。因此,您只需循环“n-1”,然后不要在最后一项后附加逗号。

      2) 一种可能的解决方案:

        ArrayList<string> items = new ArrayList<String>();
        if(addOpen);
          items.add("Open ");
        if(addHigh)
          items.add("High ");
        if(addLow)
          items.add("Low ");
        if(addSettle)
          items.add("Settle ");
      
        StringBuilder builder = new StringBuilder();
        int i=0;
        for (i=0; i < items.size() - 1; i++) {
          builder.append(items[i] + ",");
        }
        builder.append(items[i] + "FROM " + tableName);
        ...
      

      【讨论】:

        【解决方案3】:

        有几种方法。第一个是我的首选,根本不构建 SQL 语句,并且不显示字段。

        第二个是,构建字符串,去掉最后一个逗号。

        第三种是将每个字段名放入一个数组中,并循环遍历数组,而不是将结尾的逗号放在最后一个元素上。

        【讨论】:

          【解决方案4】:

          有一个常见的技巧:总是选择一个你不感兴趣的常量:

          builder.append ("SELECT 1 ");
          if (addOpen)
              builder.append (", Open ");
          if addHigh)
              builder.append (", High ");
          if (addLow)
              builder.append (", Low ");
          if (addSettle)
              builder.append (", Settle ");
          builder.append ("FROM " + tableName);
          

          另一种方法在另一个方向上起作用,尾随逗号:

          builder.append ("SELECT ");
          if (addOpen)
              builder.append ("Open, ");
          if (addHigh)
              builder.append ("High, ");
          if (addLow)
              builder.append ("Low, ");
          if (addSettle)
              builder.append ("Settle, ");
          builder.append ("1 FROM " + tableName);
          

          【讨论】:

            【解决方案5】:

            我使用的技巧(在通用的半无类型伪代码中)是:

             pad = ""    # Empty string
            
             builder = "SELECT ";
             if (addOpen)
                 builder += pad + "Open";   pad = ", ";
             if (addHigh)
                 builder += pad + "High";   pad = ", ";
             if (addLow)
                 builder += pad + "Low";    pad = ", ";
             if (addSettle)
                 builder += pad + "Settle"; pad = ", ";
             builder += "FROM " + TableName;
            

            我见过的另一种方法是始终在术语后包含逗号(或逗号空格),但在添加 FROM 子句之前将最后两个字符从值中删除。您的选择......即使您正在输出并且无法撤消追加,“pad”技术也有效。

            【讨论】:

            • 坏了。您需要在 if 主体周围使用大括号。
            【解决方案6】:

            在您的情况下,我使用类似于 Ryan Stewart 建议的解决方案,但我更喜欢 Google Guava 而不是 Apache Commons。我更喜欢这个库,因为我觉得 Apache 库非常庞大且相互关联。 下面是我将如何构建您的 SQL 字符串:

            import com.google.common.base.Joiner;
            import com.google.common.collect.Lists;
            import com.google.common.base.Preconditions;
            import com.google.common.base.Strings;
            import java.util.List;
            
            public class SqlJoiner {
                public String buildSql(
                        boolean addOpen,
                        boolean addHigh,
                        boolean addLow,
                        boolean addSettle,
                        String tableName
                ) {
                    Preconditions.checkArgument(!Strings.isNullOrEmpty(tableName));
                    Preconditions.checkArgument(addOpen | addHigh | addLow | addSettle );
            
                    final List<String> clauses = Lists.newArrayList();
            
                    if (addOpen) clauses.add("Open");
                    if (addHigh) clauses.add("High");
                    if (addLow) clauses.add("Low");
                    if (addSettle) clauses.add("Settle");
            
                    StringBuilder builder = new StringBuilder();
                    builder.append("SELECT ");
                    builder.append(Joiner.on(',').join(clauses));
                    builder.append(" FROM " + tableName);
                    return builder.toString();
                }
            
            }
            

            方法体开头的前提条件是确保至少有一个布尔选项始终为真,并且 tableName 不为 null 或为空。经常检查你的代码的前置条件,当你将来使用你的代码出错时,它会为你省去很多麻烦!

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2015-03-09
              相关资源
              最近更新 更多