-
Notifications
You must be signed in to change notification settings - Fork 459
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
John Grib
committed
Apr 22, 2017
1 parent
92b9427
commit ebe41c5
Showing
11 changed files
with
798 additions
and
56 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
package core.db; | ||
|
||
import util.ReflectionUtil; | ||
import util.UpperStringMap; | ||
|
||
import java.util.Arrays; | ||
import java.util.List; | ||
import java.util.Map; | ||
import java.util.regex.Pattern; | ||
|
||
/** | ||
* Query String 을 생성/관리한다. | ||
* Created by johngrib on 2017. 4. 22.. | ||
*/ | ||
public class Query { | ||
|
||
private static List<ValueProc> processors = Arrays.asList(new ValueProc[]{ | ||
new NullProc(), | ||
new StringProc(), | ||
new IntegerProc() | ||
}); | ||
|
||
private static String buildAlias(final String key) { | ||
return "(?i)" + Pattern.quote("${" + key + "}"); | ||
} | ||
|
||
/** | ||
* query 에 vo 의 값을 set 한다. | ||
* query 에서 replace 될 키는 ${key} 의 형태로 지정한다. | ||
* | ||
* @param sql | ||
* @param vo | ||
* @return | ||
*/ | ||
public static String build(final String sql, final Object vo) { | ||
if (vo == null) { | ||
return sql; | ||
} | ||
|
||
final Map<String, Object> map = ReflectionUtil.objMapper(vo, new UpperStringMap()); | ||
|
||
String sourceSql = sql; | ||
|
||
for (final String key : map.keySet()) { | ||
final Object val = map.get(key); | ||
final String value = processors.stream() | ||
.filter(p -> p.typeCheck(val)) | ||
.findFirst().get().proc(val); | ||
sourceSql = sourceSql.replaceAll(buildAlias(key), value); | ||
} | ||
return sourceSql; | ||
} | ||
|
||
abstract static class ValueProc { | ||
abstract String proc(Object val); | ||
|
||
abstract boolean typeCheck(Object val); | ||
} | ||
|
||
static class StringProc extends ValueProc { | ||
@Override | ||
public String proc(final Object val) { | ||
return "'" + String.valueOf(val) + "'"; | ||
} | ||
|
||
@Override | ||
boolean typeCheck(final Object val) { | ||
return val instanceof String; | ||
} | ||
} | ||
|
||
static class NullProc extends ValueProc { | ||
@Override | ||
public String proc(final Object val) { | ||
return "'" + String.valueOf(val) + "'"; | ||
} | ||
|
||
@Override | ||
boolean typeCheck(final Object val) { | ||
return val == null; | ||
} | ||
} | ||
|
||
static class IntegerProc extends ValueProc { | ||
|
||
@Override | ||
String proc(final Object val) { | ||
return String.valueOf(val); | ||
} | ||
|
||
@Override | ||
boolean typeCheck(final Object val) { | ||
return val instanceof Integer; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
package core.db; | ||
|
||
import java.sql.ResultSet; | ||
import java.sql.ResultSetMetaData; | ||
import java.sql.SQLException; | ||
import java.util.*; | ||
|
||
/** | ||
* ResultSet Wrapper | ||
* Created by johngrib on 2017. 4. 22.. | ||
*/ | ||
public class ResultData { | ||
|
||
final private List<String> labels; | ||
private ResultSet rs = null; | ||
|
||
public ResultData(final ResultSet rs) throws SQLException { | ||
this.rs = rs; | ||
this.labels = getColumnLabels(rs); | ||
} | ||
|
||
/** | ||
* column labels를 리턴한다. | ||
* @return | ||
*/ | ||
public List<String> getLabels() { | ||
return labels; | ||
} | ||
|
||
/** | ||
* column lable 을 수집한다. | ||
* @param rs | ||
* @return | ||
*/ | ||
private List<String> getColumnLabels(final ResultSet rs) { | ||
try { | ||
final int size = rs.getMetaData().getColumnCount(); | ||
final List<String> list = new ArrayList<>(size); | ||
final ResultSetMetaData meta = rs.getMetaData(); | ||
|
||
for (int i = 1; i <= size; i++) { | ||
String name = meta.getColumnName(i); | ||
list.add(name); | ||
} | ||
return list; | ||
} catch (SQLException e) { | ||
e.printStackTrace(); | ||
} | ||
return Collections.EMPTY_LIST; | ||
} | ||
|
||
public ResultSet getResultSet() { | ||
return rs; | ||
} | ||
|
||
public void close() { | ||
try { | ||
rs.close(); | ||
} catch (SQLException e) { | ||
e.printStackTrace(); | ||
} finally { | ||
rs = null; | ||
} | ||
} | ||
|
||
public boolean next() { | ||
try { | ||
return rs.next(); | ||
} catch (SQLException e) { | ||
e.printStackTrace(); | ||
} | ||
return false; | ||
} | ||
|
||
public Map<String, Object> getDataMap() { | ||
try { | ||
final Map<String, Object> data = new HashMap<>(); | ||
for (String label : labels) { | ||
data.put(label, rs.getObject(label)); | ||
} | ||
return data; | ||
|
||
} catch (SQLException e) { | ||
e.printStackTrace(); | ||
} | ||
return Collections.EMPTY_MAP; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,134 @@ | ||
package core.jdbc; | ||
|
||
import core.db.Query; | ||
import core.db.ResultData; | ||
import util.DataMethod; | ||
import util.ReflectionUtil; | ||
import util.UpperStringMap; | ||
|
||
import java.sql.Connection; | ||
import java.sql.PreparedStatement; | ||
import java.sql.ResultSet; | ||
import java.sql.SQLException; | ||
import java.util.*; | ||
|
||
/** | ||
* Created by johngrib on 2017. 4. 20.. | ||
*/ | ||
public class JdbcTemplate { | ||
|
||
/** | ||
* INSERT, UPDATE 를 수행한다. | ||
* | ||
* @param sql | ||
* @param vo | ||
* @throws SQLException | ||
*/ | ||
public void update(String sql, Object vo) throws SQLException { | ||
Connection con = null; | ||
PreparedStatement pstmt = null; | ||
try { | ||
con = ConnectionManager.getConnection(); | ||
pstmt = con.prepareStatement(Query.build(sql, vo)); | ||
pstmt.executeUpdate(); | ||
} finally { | ||
if (pstmt != null) { | ||
pstmt.close(); | ||
} | ||
|
||
if (con != null) { | ||
con.close(); | ||
} | ||
} | ||
} | ||
|
||
/** | ||
* SELECT 를 수행한다. | ||
* @param sql | ||
* @param voClass | ||
* @return | ||
* @throws SQLException | ||
*/ | ||
public <T> List<T> select(String sql, Class<T> voClass) throws SQLException { | ||
return select(sql, voClass, null); | ||
} | ||
|
||
/** | ||
* SELECT 를 수행한 결과의 첫 번째 row 를 리턴한다. | ||
* @param sql | ||
* @param voClass | ||
* @param vo | ||
* @return | ||
* @throws SQLException | ||
*/ | ||
public <T> T selectOne(String sql, Class<T> voClass, Object vo) throws SQLException { | ||
final List<T> list = select(sql, voClass, vo); | ||
return (list.size() > 0) ? list.get(0) : null; | ||
} | ||
|
||
/** | ||
* SELECT 를 수행한다. | ||
* | ||
* @param sql | ||
* @param voClass | ||
* @return | ||
* @throws SQLException | ||
*/ | ||
public <T> List<T> select(String sql, Class<T> voClass, Object vo) throws SQLException { | ||
|
||
ResultSet rs = null; | ||
final String query = Query.build(sql, vo); | ||
try ( | ||
final Connection con = ConnectionManager.getConnection(); | ||
final PreparedStatement pstmt = con.prepareStatement(query); | ||
) { | ||
rs = pstmt.executeQuery(); | ||
|
||
final ResultData rd = new ResultData(rs); | ||
final List<T> list = new ArrayList<>(rs.getFetchSize()); | ||
final Map<String, DataMethod> setters = ReflectionUtil.getSetterMemberMap(voClass, new UpperStringMap()); | ||
final List<String> labels = rd.getLabels(); | ||
|
||
while (rd.next()) { | ||
|
||
final T row = ReflectionUtil.newSimpleInstance(voClass); | ||
|
||
for (String label: labels) { | ||
DataMethod setter = setters.get(label); | ||
setVoFromResultSet(setter, rd.getResultSet(), row); | ||
} | ||
list.add(row); | ||
} | ||
return list; | ||
} finally { | ||
if (rs != null) { | ||
rs.close(); | ||
} | ||
} | ||
} | ||
|
||
/** | ||
* ResultSet 의 데이터를 vo 에 매핑한다. | ||
* @param m | ||
* @param rs | ||
* @param vo | ||
*/ | ||
private void setVoFromResultSet(final DataMethod m, final ResultSet rs, Object vo) { | ||
try { | ||
if (String.class.equals(m.type)) { | ||
m.setter(vo, rs.getString(m.fieldName)); | ||
return; | ||
} | ||
if (Integer.class.equals(m.type)) { | ||
m.setter(vo, rs.getInt(m.fieldName)); | ||
return; | ||
} | ||
if (Double.class.equals(m.type)) { | ||
m.setter(vo, rs.getInt(m.fieldName)); | ||
return; | ||
} | ||
} catch (SQLException e) { | ||
e.printStackTrace(); | ||
} | ||
} | ||
} |
Oops, something went wrong.