°í±Þ PreparedStatement¸¦ »ç¿ëÇÏ¿© JCBC Äڵ忡 ·Î±ë Ãß°¡Çϱâ
Jens
Wyke Consultant, IBM 2003³â 5¿ù 20ÀÏ
JDBC java.sql.PreparedStatement
ÀÎÅÍÆäÀ̽º·Î °£´ÜÈ÷ È®ÀåÇÔÀ¸·Î¼ Äõ¸® ·Î±ëÀÇ ¿¡·¯¸¦ ÁÙÀÏ ¼ö ÀÖ´Ù. Äڵ嵵 ´õ ±ò²ûÇØÁø´Ù. IBM
e-ºñÁî´Ï½º ÄÁ¼³ÅÏÆ®ÀÎ Jens Wyke°¡ ·¡ÇÎ ±â¼úÀ» ¼³¸íÇÑ´Ù.
´ëºÎºÐÀÇ °æ¿ì, JDBC PreparedStatement ´Â µ¥ÀÌÅͺ£À̽º Äõ¸®¸¦ ½±°Ô
¼öÇàÇÒ ¼ö ÀÖµµ·Ï ÇÑ´Ù. ¶ÇÇÑ Àüü ¾ÖÇø®ÄÉÀÌ¼Ç ÆÛÆ÷¸Õ½º¿¡µµ ¶Ñ·ÇÇÑ Çâ»óÀ» º¸ÀδÙ. ÇÏÁö¸¸
PreparedStatement ÀÎÅÍÆäÀ̽º´Â Äõ¸® ¹®ÀåÀ» ·Î±ëÇÒ ¶§ ºÎÁ·ÇÑÁ¡ÀÌ ÀÖ´Ù.
PreparedStatement ÀÇ °Á¡ÀÌ ´Ù¾ç¼º¿¡ ÀÖ´Â ¸¸Å, ÁÁÀº ·Î±ë ¿£Æ®¸® ¶ó¸é
µ¥ÀÌÅͺ£À̽º·Î º¸³»Áö´Â SQLÀÌ ½ÇÁ¦ ¸Å°³º¯¼ö °ªÀ» ´ëüÇÑ ¸Å°³º¯¼ö Ç÷¹À̽ºÈ¦´õ¸¦ ¾î¶»°Ô ´Ù·ç´ÂÁö¸¦ ¼³¸íÇؾß
ÇÑ´Ù.
ÀÌ ±Û¿¡¼´Â Äõ¸® ·Î±ëÀ» À§ÇØ JDBC PreparedStatement ÀÎÅÍÆäÀ̽º¸¦
È®ÀåÇÏ´Â ¹æ¹ýÀ» ¹è¿î´Ù. LoggableStatement Ŭ·¡½º´Â
PreparedStatement ÀÎÅÍÆäÀ̽º¸¦ ±¸ÇöÇÏÁö¸¸ ·Î±ë¿¡ ÀûÇÕÇÑ Æ÷¸ËÀ¸·Î Äõ¸®
½ºÆ®¸µÀ» ¾ò±âÀ§ÇÑ ¸Þ¼Òµå¸¦ Ãß°¡ÇÑ´Ù. LoggableStatement Ŭ·¡½º¸¦ »ç¿ëÇϸé
·Î±ë Äڵ忡¼ ¿¡·¯¸¦ ÁÙÀÏ ¼ö ÀÖ°í °ü¸®°¡ ½¬¿î Äڵ带 ¸¸µé¾î ³¾ ¼ö ÀÖ´Ù.
ÀϹÝÀûÀÎ ·Î±ë
¼Ö·ç¼Ç Listing 1Àº µ¥ÀÌÅͺ£À̽º Äõ¸®¸¦ ¸¸µé ¶§
PreparedStatement ÀÇ ÀüÇüÀûÀÎ »ç¿ë ¿¹Á¦¸¦ º¸¿©ÁÖ°í ÀÖ´Ù. ¿¹Á¦·Î SQL
query SELECT ¸¦ »ç¿ëÇÏ°ÚÁö¸¸ DELETE ,
UPDATE , INSERT °°Àº ±âŸ SQL ¹®Àåµéµµ Àû¿ëÇÒ
°ÍÀÌ´Ù. Listing 1. ÀϹÝÀûÀÎ SQL µ¥ÀÌÅͺ£À̽º
Äõ¸®
String sql = "select foo, bar from foobar where foo < ? and bar = ?";
String fooValue = new Long(99);
String barValue = "christmas";
Connection conn = dataSource.getConnection();
PreparedStatement pstmt = conn.prepareStatement(sql);
pstmt.setLong(1,fooValue);
pstmt.setString(2,barValue);
ResultSet rs = pstmt.executeQuery();
// parse result...
|
Listing 1¿¡¼ Äõ¸®¸¦ À§ÇÑ ÁÁÀº ·Î±× ¿£Æ®¸®¶ó¸é ´ÙÀ½°ú °°À» °ÍÀÌ´Ù:
Executing query: select foo,bar from foobar where foo < 99 and
bar='christmas'
|
±×·¯ÇÑ ¿£Æ®¸®¿ë ·Î±ë Äڵ尡 ¾î¶»°Ô º¸ÀÌ´ÂÁö¿¡ ´ëÇÑ ¿¹Á¦µµ ÀÖ´Ù. Listing 1ÀÇ ¹°À½Ç¥´Â °¢°¢ÀÇ
¸Å°³º¯¼ö °ªÀ¸·Î ´ëüµÇ¾ú´Ù.
System.out.println("Executing query: select foo, bar from foobar where foo
< "+fooValue+" and bar = '+barValue+"'")
|
º¸´Ù ³ªÀº Á¢±Ù¹æ½ÄÀ¸·Î´Â ¸Þ¼Òµå¸¦ ¸¸µå´Â °ÍÀÌ´Ù.
replaceFirstQuestionMark ¸¦ È£ÃâÇغ»´Ù. ÀÌ°ÍÀº Äõ¸® ½ºÆ®¸µÀ» °¡Áö°í
¹°À½Ç¥¸¦ ¸Å°³º¯¼ö °ªÀ¸·Î ´ëüÇÑ´Ù. (Listing 2). ¸Þ¼Òµå¸¦ »ç¿ëÇϸé SQL ¹®À» ¼³¸íÇϱâ À§ÇÑ Áߺ¹
½ºÆ®¸µÀ» ¸¸µé ÇÊ¿ä°¡ ¾ø´Ù. Listing 2. ½ºÆ®¸µ ´ëü¸¦ À§ÇØ
replaceFirstQuestionMark »ç¿ëÇϱâ
// listing 1 goes here
sql = replaceFirstQuestionMark(sql, fooValue);
sql = replaceFirstQuestionMark(sql, barValue);
System.out.println("Executing query: "+sql);
|
±¸ÇöÀº ½±Áö¸¸ ¼Ö·ç¼ÇÀº ÀÌ»óÀûÀÎ °ÍÀº ¾Æ´Ï´Ù. SQL ÅÛÇø´ÀÌ º¯°æµÉ ¶§ ¸¶´Ù ·Î±ë Äڵ嵵 º¯°æµÈ´Ù´Â °ÍÀÌ
¹®Á¦ÀÌ´Ù. ½Ç¼öÇϱ⠽¬¿î ºÎºÐÀÌ´Ù. Äõ¸®´Â ¹Ù²îÁö¸¸ ·Î±ë Äڵ带 ¾÷µ¥ÀÌÆ® ÇÏ´Â °ÍÀ» ÀØÀ» ¼ö ÀÖ°í µ¥ÀÌÅͺ£À̽º¿¡
º¸³»Áø Äõ¸®¿Í ¸ÂÁö ¾Ê´Â ·Î±ë ¿£Æ®¸®·Î ³¡³¾ ¼ö ÀÖ´Ù. µð¹ö±ëÀº ¾Ç¸ùÀÌ´Ù!
°¢°¢ÀÇ ¸Å°³º¯¼ö(fooValue ¿Í barValue )¸¦
»ç¿ëÇϵµ·Ï ÇÏ´Â µðÀÚÀÎÀÌ ÇÊ¿äÇÏ´Ù. ½ÇÁ¦ °ªÀ¸·Î ´ëüµÈ ¸Å°³º¯¼ö Ç÷¹À̽ºÈ¦´õ°¡ ÀÖ´Â Äõ¸® ½ºÆ®¸µÀÌ ¸¶À½¿¡ µç´Ù.
java.sql.PreparedStatement ´Â ±×¿Í °°Àº ¸Þ¼Òµå°¡ ¾ø±â ¶§¹®¿¡ ¿ì¸®°¡
±×°ÍÀ» ±¸ÇöÇØ¾ß ÇÑ´Ù.
¸ÂÃã
¼Ö·ç¼Ç ¿ì¸®°¡ ±¸ÇöÇÑ PreparedStatement ´Â JDBC
µå¶óÀ̹ö°¡ Á¦°øÇÑ "½ÇÁ¦ ¹®Àå" ÁÖÀ§¿¡¼ ·¡ÆÛ·Î ÀÛµ¿ÇÑ´Ù. ·¡ÆÛ ¹®ÀåÀº ¸ðµç ¸Þ¼Òµå È£Ãâ(¿¹¸¦ µé¾î,
setLong(int, long) °ú
setString(int,String) )À» "½ÇÁ¦ ¹®Àå"À¸·Î Àü´ÞÇÑ´Ù. ÀÌ Àü¿¡ °ü·ÃµÈ
¸Å°³º¯¼ö °ªÀ» ÀúÀåÇÏ¿© ·Î±ë ¾Æ¿ôDzÀ» ¸¸µå´Âµ¥ »ç¿ëµÉ ¼ö ÀÖµµ·Ï ÇÑ´Ù.
Listing 3Àº LoggableStatement Ŭ·¡½º°¡
java.sql.PreparedStatement ¸¦ ±¸ÇöÇÏ´Â ¹æ¹ýÀ» º¸¿©ÁÖ°í ÀÖ´Ù.
JDBC Ä¿³Ø¼Ç°ú ÀÎDzÀ¸·Î¼ SQL ÅÛÇø´À» »ç¿ëÇÏ¿© ¸¸µé¾îÁö´Â ¹æ¹ýÀ» º¸¿©ÁØ´Ù. Listing 3. java.sql.PreparedStatement¸¦ ±¸ÇöÇÏ´Â
LoggableStatement
public class LoggableStatement implements java.sql.PreparedStatement {
// used for storing parameter values needed
// for producing log
private ArrayList parameterValues;
// the query string with question marks as
// parameter placeholders
private String sqlTemplate;
// a statement created from a real database
// connection
private PreparedStatement wrappedStatement;
public LoggableStatement(Connection connection, String sql)
throws SQLException {
// use connection to make a prepared statement
wrappedStatement = connection.prepareStatement(sql);
sqlTemplate = sql;
parameterValues = new ArrayList();
}
}
|
LoggableStatement
ÀÛµ¿ ¹æ¹ý Listing 4´Â LoggableStatement °¡
saveQueryParamValue() ¸Þ¼Òµå·Î È£ÃâÀ» Ãß°¡ÇÏ°í
setLong °ú setString ¸Þ¼Òµå¸¦ À§ÇÑ "½ÇÁ¦ ¹®Àå"¿¡
´ëÇÑ »óÀÀ ¸Þ¼Òµå¸¦ È£ÃâÇÏ´Â °ÍÀ» º¸¿©ÁÖ°í ÀÖ´Ù. saveQueryParamValue()
È£ÃâÀº ºñ½ÁÇÑ ¹æ½ÄÀ¸·Î ¸Å°³º¯¼ö ¼³Á¤(¿¹¸¦ µé¾î, setChar ,
setLong , setRef ,
setObj )¿¡ »ç¿ëµÈ ¸ðµç ¸Þ¼Òµå¿¡ Ãß°¡µÈ´Ù.
executeQuery ¸Þ¼Òµå°¡
saveQueryParamValue() ¸¦ È£ÃâÇÏÁö ¾Ê°í ¾î¶»°Ô ·¡ÇεǴÂÁö¸¦ º¸¿©ÁÖ°í
ÀÖ´Ù. ÀÌ°ÍÀº "¸Å°³º¯¼ö ¼³Á¤" ¸Þ¼Òµå°¡ ¾Æ´Ï±â ¶§¹®ÀÌ´Ù. Listing 4. LoggableStatement ¸Þ¼Òµå
public void setLong(int parameterIndex, long x)
throws java.sql.SQLException {
wrappedStatement.setLong(parameterIndex, x);
saveQueryParamValue(parameterIndex, new Long(x));
}
public void setString(int parameterIndex, String x)
throws java.sql.SQLException {
wrappedStatement.setString(parameterIndex, x);
saveQueryParamValue(parameterIndex, x);
}
public ResultSet executeQuery() throws java.sql.SQLException {
return wrappedStatement.executeQuery();
}
|
saveQueryParamValue() ¸Þ¼Òµå´Â Listing 5¿¡¼ º¼ ¼ö ÀÖ´Ù.
°¢°¢ÀÇ ¸Å°³º¯¼ö °ªÀ» String Ç¥½Ã·Î º¯È¯Çϸé¼
getQueryString ¸Þ¼Òµå¿¡ ÀÇÇØ ³ªÁß¿¡ »ç¿ëµÉ ¼ö ÀÖµµ·Ï À̸¦ ÀúÀåÇÑ´Ù.
±âº»ÀûÀ¸·Î ÇϳªÀÇ °´Ã¼´Â toString ¸Þ¼Òµå¸¦ »ç¿ëÇÏ´Â
String À¸·Î º¯È¯µÇ°ÚÁö¸¸ °´Ã¼°¡ String À̳ª
Date ¶ó¸é ½Ì±Û ÄõÆ® ºÎÈ£ ('')°¡ ºÙ´Â´Ù.
getQueryString() ¸Þ¼Òµå·Î´Â ·Î±×¿¡¼ ´ëºÎºÐÀÇ Äõ¸®¸¦ º¹»çÇÏ¿© º¯°æÇÏÁö ¾Ê°í
´ëÈÇü SQL ÇÁ·Î¼¼¼¿¡ ºÙÀÏ ¼ö ÀÖ´Ù. Å×½ºÆðú µð¹ö±ë¿¡ ¾²ÀδÙ. ÇÊ¿äÇÑ °æ¿ì ¸Þ¼Òµå¸¦ ¼öÁ¤ÇÏ¿© ´Ù¸¥ Ŭ·¡½ºÀÇ
¸Å°³º¯¼ö °ªÀ» º¯È¯ÇÒ ¼ö ÀÖ´Ù. Listing 5.
saveQueryParamValue() ¸Þ¼Òµå
private void saveQueryParamValue(int position, Object obj) {
String strValue;
if (obj instanceof String || obj instanceof Date) {
// if we have a String, include '' in the saved value
strValue = "'" + obj + "'";
} else {
if (obj == null) {
// convert null to the string null
strValue = "null";
} else {
// unknown object (includes all Numbers), just call toString
strValue = obj.toString();
}
}
// if we are setting a position larger than current size of
// parameterValues, first make it larger
while (position >= parameterValues.size()) {
parameterValues.add(null);
}
// save the parameter
parameterValues.set(position, strValue);
}
|
¸ðµç ¸Å°³º¯¼öµéÀÌ Ç¥ÁØ ¸Þ¼Òµå¸¦ »ç¿ëÇÏ¿© ¼³Á¤µÇ¸é LoggableStatement ¿¡
getQueryString() ¸Þ¼Òµå¸¦ È£ÃâÇÏ¿© Äõ¸® ½ºÆ®¸µÀ» ¾ò´Â´Ù. ¸ðµç ¹°À½Ç¥´Â
½ÇÁ¦ ¸Å°³º¯¼ö °ªÀ¸·Î ´ëüµÈ´Ù.
LoggableStatement
»ç¿ëÇϱâ Listing 6Àº Listings 1°ú 2ÀÇ Äڵ尡
LoggableStatement ¸¦ »ç¿ëÇϱâ À§ÇØ ¾î¶»°Ô º¯°æµÇ¾ú´ÂÁö¸¦ º¸¿©ÁÖ°í ÀÖ´Ù.
LoggableStatement ¸¦ ¿ì¸®ÀÇ ¾ÖÇø®ÄÉÀÌ¼Ç Äڵ忡 µµÀÔÇϸé Áߺ¹µÈ ¸Å°³º¯¼ö
¹®Á¦¸¦ ÇØ°áÇÒ ¼ö ÀÖ´Ù. SQL ÅÛÇø´ÀÌ º¯°æµÇ¸é, PreparedStatement ¿¡
´ëÇÑ ¸Å°³º¯¼ö ¼³Á¤ È£ÃâÀ» ¾÷µ¥ÀÌÆ®ÇÏ¸é µÈ´Ù. º¯°æ»çÇ×Àº ·Î±ë Äڵ带 ¾÷µ¥ÀÌÆ® ÇÏÁö ¾Ê°íµµ ·Î±ë ¾Æ¿ôDz¿¡
¹Ý¿µµÈ´Ù. Listing 6. LoggableStatement
ÀÛµ¿
String sql = "select foo, bar from foobar where foo < ? and bar = ?";
long fooValue = 99;
String barValue = "christmas";
Connection conn = dataSource.getConnection();
PreparedStatement pstmt;
if(logEnabled) // use a switch to toggle logging.
pstmt = new LoggableStatement(conn,sql);
else
pstmt = conn.prepareStatement(sql);
pstmt.setLong(1,fooValue);
pstmt.setString(2,barValue);
if(logEnabled)
System.out.println("Executing query: "+
((LoggableStatement)pstmt).getQueryString());
ResultSet rs = pstmt.executeQuery();
|
Âü°íÀÚ·á
|
|