JAVA:我想清楚使用像这样的字符串
String str = " SELECT "
+ "field1, "
+ "field2, "
+ "field3 "
+ " FROM table1; ";
好或不以这种方式使用。
根据字符串的最佳做法询问,不要用于连接。
这是非常短的查询,但实际上我们有非常非常大的查询。这只是一个例子。所以我只想确认我没有做任何错误。
答案 0 :(得分:3)
String
与+
运算符的连接在某些上下文中可能被视为不良做法,即如果在编译时它不能被StringBuilder
调用自动替换。
一般情况下,如果您的字段是常量或只是一次初始化,则String
与+
的连接完全没问题。
但是,如果您正在动态构建String
并循环/递归,那么最好使用StringBuilder
(或StringBuffer
进行线程安全连接)。
答案 1 :(得分:2)
这没关系,与将其写成一个字符串完全相同:
String str = " SELECT field1, field2, field3 FROM table1; ";
如果要连接字符串文字,编译器将在编译时进行连接,因此生成的字节码完全相同,无论您是像编写它还是作为一个字符串文字一样编写它。
答案 2 :(得分:1)
我非常怀疑field1和field2和table1是预先知道的,我认为它们是某个函数的参数。
在这种情况下,应该使用StringBuilder。即使你用加号连接,你仍然(几乎总是)得到一个StringBuilder,只看一下字节码。这是一个参考:
“实现可以选择一步执行转换和连接,以避免创建然后丢弃中间String对象。为了提高重复字符串连接的性能,Java编译器可以使用StringBuffer类或类似的减少通过评估表达式创建的中间String对象数量的技术。“。15.18.1
请记住,如果你要循环,会有性能损失。
答案 3 :(得分:1)
您的示例很好,因为它只涉及 literals ,编译器将在编译时进行连接。
但如果你有:
String str = " SELECT "
+ "field1, "
+ someVariable
+ "field3 "
+ " FROM table1; ";
...然后编译器只能为你处理它的一部分,在运行时产生这个:
String str = " SELECT field1, "
+ someVariable
+ "field3 FROM table1; ";
它在运行时发生的方式是通过StringBuilder
,听起来很棒,但遗憾的是效率很低,实际上是:
StringBuilder sb1 = new StringBuilder();
sb1.append(" SELECT field1, ");
sb1.append(someVariable);
String temp = sb1.toString();
StringBuilder sb2 = new StringBuilder();
sb2.append(temp);
sb2.append("field3 FROM table1; ");
String str = sb2.toString();
它不仅创建多个StringBuilder
实例并对toString
进行不必要的调用,而且它使用默认构造函数,它只为其数组中的16个字符的字符串分配足够的空间(最后一个选中)。所以StringBuilder
可能必须在至少重新分配其内部数组一次。布莱克,对吗? (等等......)
与您自己做的事情相比:
String str = (new StringBuilder(200))
.append(" SELECT " +
"field1, ")
.append(someVariable)
.append("field3 " +
" FROM table1; ")
.toString();
效率更高。
但 更好 ?看起来很糟糕,很难维护。从性能的角度来看,你必须在紧密的循环中做到这一点。
如果您遇到有助于解决的性能问题,那就更好了。
如果不这样做,那就不是“更好”,因为代码不太清楚。
如果你只处理文字,这些都不重要。
答案 4 :(得分:1)
+
被认为是错误的。让我们说你有
String s = "f";
for (int i=0; i<100; i++){
s = s + "o";
}
在这种情况下
s = s + "o";
将编译为
s = new StringBuilder(f).append("o").toString();
所以在每次迭代中你都在创建新的StringBuilder,你正在将s
的当前内容复制到它,然后你要添加o
并通过调用toString
来重新创建新的String实例存储在s
引用中。正如你所看到的那样,很多事情要做,特别是coppying和创建String的新实例,执行的时间取决于字符串的长度。
这样做的首选方法是创建自己的StringBuilder,在循环中追加你想要的东西,并在循环结束后从StringBuilder的内容创建新的String对象。像
这样的东西StringBuilder sb = new StringBuilder("f");
for (int i=0; i<100; i++){
sb.append("o");
}
String s = sb.toString();
但是在你的情况下,因为你在编译时常量上运行而不能改变,所以编译器能够找出
String str = " SELECT "
+ "field1, "
+ "field2, "
+ "field3 "
+ " FROM table1; ";
只能是" SELECT field1, field2, field3 FROM table1; "
,所以它会在编译时连接起来,所以你的str将被编译为
String str = " SELECT field1, field2, field3 FROM table1; ";
答案 5 :(得分:1)
你在这里做的事情并没有错。但是,由于以下原因,这很尴尬:
不合理:所有操作员和报价都让人讨厌阅读
容易出错:修改此内容以省略子字符串中的空格并破坏查询
不方便:您无法将查询复制到SQL工具中,而无需停止并删除所有运算符和引号。
您可以将这样的SQL提取到配置文件中,可以使用属性文件或XML(使用CDATA)。您可以在Spring Integration - Externalizing JDBC Queries
查看示例