For what it's worth, I'd recommend that you look at iBatis, which IMHO, makes handwritten DAOs and DTOs with JDBC completely obsolete.
Before iBatis I use to keep my SQL in a separate SQL file and retrieved the correct SQL when I needed it. I don't use it anymore... since this is only marginally better than SQL in the actual Java code.
The syntax of the SQL file is as follows:
-- I added comments like this...
[id] {
any SQL statement... (quite frankly any text).
}
[id2] {
...
}
...
Then, a simple Parser class of the following:
public class SQLParser {
private static Logger logger = LoggerUtility.getLogger(SQLParser.class);
private String raw;
private Map<String, String> sql;
public SQLParser(InputStream is) {
sql = new HashMap<String, String>();
try {
read(is);
parse();
} catch (IOException e) {
logger.debug(LoggerCodes.TRACE, "Input Stream could not be successfull read!");
}
}
private void read(InputStream is) throws IOException {
StringBuilder builder = new StringBuilder();
BufferedReader in = new BufferedReader(new InputStreamReader(is));
String line = in.readLine();
while (line != null) {
builder.append(line + "\n");
line = in.readLine();
}
raw = builder.toString();
}
public String getSql(String sqlId) {
return sql.get(sqlId);
}
public PreparedStatement getSql(Connection connection, String sqlId) throws SQLException {
String statement = sql.get(sqlId);
return connection.prepareStatement(statement);
}
private void parse() {
if (raw == null) {
logger.debug(LoggerCodes.TRACE, "No String to parse for SQL statements!");
return;
}
String regex = "\\.*\\[(\\S*)\\]\\s*\\{\\s*([^\\}]*)\\s*\\}";
Pattern p = Pattern.compile(regex);
Matcher m = p.matcher(raw);
while (m.find()) {
String key = m.group(1);
String body = m.group(2);
logger.debug("Adding " + key + " to SQL map.");
sql.put(key, body.trim());
}
}
}
Then simply create a new instance of the above and call sqlParser.getSql(id) to obtain the correct SQL.