如何“优雅”地生成字符串在Java中?

发布于 2024-11-03 08:08:31 字数 692 浏览 1 评论 0原文

我想生成一个字符串,例如 sql 命令:

   "INSERT INTO xxx VALUES(XXX, XXX, XXX)"

目前我使用 StringBuilder 和一些 String 常量(如“INSERT INTO”)来连接表名称和插入值的输入字符串参数。

然而,除了性能问题之外,这种简单的串联看起来并不优雅。 还有其他方法可以做到这一点吗?

在我看来,JDBC 的准备语句就是这种“命令模板”的一个很好的例子:

PreparedStatement pstmt=connection.createPreparedStatement("INSERT INTO ? VALUES(?,?,?)");

然后您可以设置表名和插入的值。

pstmt.setString(1,"tableA");
pstmt.setInt(2, 100);
...

但是,我不能使用准备好的语句,因为我想要的只是字符串...

并且有人给了我一些使用 java.util.Regex 或 JavaCC 来生成字符串的提示。 但据我所知,无论为某些代码优雅问题选择什么,Java String 都必须由诸如 StringBuilder 之类的东西生成,对吗???

I want to generate a string such as sql command:

   "INSERT INTO xxx VALUES(XXX, XXX, XXX)"

currently I use StringBuilder and some String constant like "INSERT INTO" to concatenate input String parameters for the table name and inserted values.

However, other than performance issue, this plain concatenation looks not elegant.
Is there any other way of doing this?

In my opinion, JDBC's prepared statement is one good example of such a "command template":

PreparedStatement pstmt=connection.createPreparedStatement("INSERT INTO ? VALUES(?,?,?)");

then you can set the table name and inserted value.

pstmt.setString(1,"tableA");
pstmt.setInt(2, 100);
...

However, I can not use prepared statement, since what I want is just String...

And someone give me some hint to use java.util.Regex or JavaCC to produce the String.
But as far as I can see, whatever is chosen for some code elegancy issue, Java String must be generated by something like StringBuilder, right???

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

jJeQQOZ5 2024-11-10 08:08:31

您可以使用 String.format():

String.format("insert into %s values('%s', '%s', '%s')", "user", "user123", "pass123", "yellow");

但值得注意的是,任何这些“字符串构建”技术都会让您容易受到 SQL 注入攻击。您确实应该尽可能使用 JDBC 参数化查询。

编辑以在字符串周围添加引号。

You could use String.format():

String.format("insert into %s values('%s', '%s', '%s')", "user", "user123", "pass123", "yellow");

It's worth noting though, that any of these "string building" techniques leave you vulnerable to SQL injection attacks. You should really use JDBC parameterised queries wherever possible.

Edited to add quotes around strings.

九公里浅绿 2024-11-10 08:08:31

也许您正在寻找 java.text.MessageFormat< /a>

 int planet = 7;
 String event = "a disturbance in the Force";

 String result = MessageFormat.format(
     "At {1,time} on {1,date}, there was {2} on planet {0,number,integer}.",
     planet, new Date(), event);

Maybe you are looking for java.text.MessageFormat

 int planet = 7;
 String event = "a disturbance in the Force";

 String result = MessageFormat.format(
     "At {1,time} on {1,date}, there was {2} on planet {0,number,integer}.",
     planet, new Date(), event);
戏剧牡丹亭 2024-11-10 08:08:31

您是否尝试过仅使用“+”?

String sql = "INSERT INTO " + table
           +" VALUES(" + value1 + ", " + value2 + ", " = value3+")";

Have you tried just using '+' ?

String sql = "INSERT INTO " + table
           +" VALUES(" + value1 + ", " + value2 + ", " = value3+")";
撩动你心 2024-11-10 08:08:31

考虑到其他各种答案,但没有一个得到您的认可,也许您应该接受实际的字符串生成(无 JPA、PreparedStatement 等)将相当不优雅,并创建一个带有静态 sql 生成器的实用程序类。

编辑 显示一个示例,说明如果无法选择预先存在的类(例如PreparedStatement),我将如何处理此问题。它不是最优雅的,但它做了它应该做的事情(假设我正确地输入了所有内容)。

public class SQLUtil {
    public static String generateInsertSQL(String tableName, List<CustomParameter> parmList){
        StringBuilder sb = new Stringbuilder();
        sb.append("insert into ");
        sb.append(tableName);
        sb.append(" values (");
        for (int i = 0; i < parmList.size(); i++){
            customParameter parm = parmList.get(i);
            switch (parm.getType()) { // enum with your desired sql types
                case ParmTypes.String:
                    sb.append("'");
                    sb.append(StringEscapeUtils.escapeSql(String.valueOf(parm.getValue())));
                    sb.append("'");
                    break;
                case ParmTypes.Integer:
                    sb.append(Integer.valueOf(parm.getValue()));
                    break;
            }
            if (i < parmList.size() - 1) sb.append(",");
        }
        sb.append(")");
        return sb.toString();
    }
}

这样,您的业务代码将保持相对优雅,并且您可以随心所欲地使用 SQL 字符串生成。您还可以使用它来“保证”您的所有插入免受 SQL 注入等攻击。

Given the variety of other answers and none of them met your approval, perhaps you should accept that the actual String generation (sans JPA, PreparedStatement, etc.) is going to be fairly inelegant and create a utility class with static sql generators.

edit Showing an example of how I'd go about this if a pre-existing class such as PreparedStatement weren't an option. It's not the most elegant, but it does what it's supposed to (assuming I typed it all in correctly).

public class SQLUtil {
    public static String generateInsertSQL(String tableName, List<CustomParameter> parmList){
        StringBuilder sb = new Stringbuilder();
        sb.append("insert into ");
        sb.append(tableName);
        sb.append(" values (");
        for (int i = 0; i < parmList.size(); i++){
            customParameter parm = parmList.get(i);
            switch (parm.getType()) { // enum with your desired sql types
                case ParmTypes.String:
                    sb.append("'");
                    sb.append(StringEscapeUtils.escapeSql(String.valueOf(parm.getValue())));
                    sb.append("'");
                    break;
                case ParmTypes.Integer:
                    sb.append(Integer.valueOf(parm.getValue()));
                    break;
            }
            if (i < parmList.size() - 1) sb.append(",");
        }
        sb.append(")");
        return sb.toString();
    }
}

This way, your business code will remain relatively elegant and you can play around with the SQL String generation to your heart's content. You can also use this to "guarantee" all your inserts are protected against such attacks as SQL injection.

厌味 2024-11-10 08:08:31

使用 StringTemplate (http://www.stringtemplate.org/) 也许是一个不错的选择:

这看起来更好,对吧?

StringTemplate insert = new StringTemplate("INSERT $table$ VALUES ($value; separator=\",\"$)");
insert.setAttribute("table", "aTable");
String[] values = {"1", "1", "'aaa'", "'bbb'"};
for(int i = 0;i < values.length;i++){   
  insert.setAttribute("value", values[i]);  
}
System.out.println(insert.toString());

Use StringTemplate (http://www.stringtemplate.org/) maybe a good choice:

This looks better, right?

StringTemplate insert = new StringTemplate("INSERT $table$ VALUES ($value; separator=\",\"$)");
insert.setAttribute("table", "aTable");
String[] values = {"1", "1", "'aaa'", "'bbb'"};
for(int i = 0;i < values.length;i++){   
  insert.setAttribute("value", values[i]);  
}
System.out.println(insert.toString());
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文