I would like to replace named parameters in a string with values, like when using Python's % operator. Spring supports something very similar to the functionality I need with NamedParameterUtils, but for some reason it's tightly coupled to Jdbc and replacing those named-parameters with question marks.
So, if I want to do ":a is :b" % {"a":"Java", "b":"Beautiful"}
must I resort to using some heavy artillery like Velocity?开发者_开发百科 or am I missing something simple?
Update: used Dmitry's code to write my own simple version:
public static String formatSqlWithNamedParams(String sqlTemplate, Map<String, Object> params){
StringWriter writer = new StringWriter();
Pattern var = Pattern.compile("\\$\\{\\s*([\\w\\[\\]\\(\\)\\.]+)\\s*\\}");
Matcher match = var.matcher(sqlTemplate);
int offset = 0;
while (match.find()) {
writer.write(sqlTemplate.substring(offset, match.start()));
String key = match.group(1);
Object val = params.get(key);
writer.write(val.toString());
offset = match.end();
}
writer.write(sqlTemplate.substring(offset));
return writer.toString();
}
It should take about 50 lines of code to write what you want.
Here's an excerpt from a "TrivialTemplate" I wrote a while back, which does something very similar:
private final Pattern var = Pattern
.compile("\\{\\s*([\\w\\[\\]\\(\\)\\.]+)\\s*\\}");
private final PropertyUtilsBean bean = new PropertyUtilsBean();
private final Object data;
public TrivialTemplate(Object data) {
this.data = data;
}
public void process(BufferedReader reader, PrintWriter writer) {
String line = null;
try {
while ((line = reader.readLine()) != null) {
Matcher match = var.matcher(line);
int offset = 0;
while (match.find()) {
writer.write(line.substring(offset, match.start()));
String key = match.group(1);
if (!isBlank(key)) {
Object val = bean.getNestedProperty(data, key
.toLowerCase());
writer.write(val != null ? val.toString() : "{null}");
} else {
writer.write("{null}");
}
offset = match.end();
}
writer.write(line.substring(offset));
writer.println();
}
} catch (Throwable t) {
throw new RuntimeException("template error", t);
}
}
I'm using BeanUtils to support arbitrary data objects, but you can just as easily limit it to Maps.
精彩评论