(1));
- return (T) runPreparedSQL(ps);
- }
-
- /**
- * In-line style execute query and force return a long value, runtime exception
- * may throw if result can not be cast to long.
- */
- public long qryLongValue(Object... inlineSQL) {
- return ((Number) qryObject(inlineSQL)).longValue();// NOSONAR
- }
-
- /**
- * In-line style execute query and force return a int, runtime exception may
- * throw if result can not be cast to int.
- */
- public int qryIntValue(Object... inlineSQL) {
- return ((Number) qryObject(inlineSQL)).intValue();// NOSONAR
- }
-
- /**
+
+ public DbPro() {
+ super();
+ }
+
+ public DbPro(DataSource ds) {
+ super(ds);
+ }
+
+ public DbPro(DataSource ds, Dialect dialect) {
+ super(ds, dialect);
+ }
+
+ /**
+ * Quite execute a SQL, do not throw any exception, if any exception happen,
+ * return -1
+ */
+ public int quiteExecute(String... sqls) {
+ int result = 0;
+ for (String sql : sqls)
+ try {
+ execute(sql);
+ } catch (Exception e) {
+ result = -1;
+ }
+ return result;
+ }
+
+ public void ________prepareMethods________() {// NOSONAR
+ }
+
+ /**
+ * Prepare a PreparedSQL for iXxxx (Single SQL) style, unknown objects (include
+ * null) will automatically looked as SQL pieces, more detail see doPrepare
+ * method
+ */
+ public PreparedSQL prepare(Object... items) {
+ return doPrepare(true, items);
+ }
+
+ /**
+ * Prepare a PreparedSQL for iXxxx (In-line) style or pXxxx style, For in-line
+ * style, unknown items be treated as String, SQL parameters must written in
+ * param() method, for example:
+ *
+ * ctx.iQuery(new SimpleCacheHandler(), connection, "select u.** from users u
+ * where u.age>?", param(20)," and u.id=?", param("001"), MapListHandler.class);
+ *
+ *
+ * pXxxx style only allow first appeared String as SQL, left unknown items will
+ * be treated as SQL parameters, for example:
+ *
+ * ctx.pQuery(MapListHandler.class, "select * from users where age>? and id=?",
+ * 20 , "001" , connection, new PaginHandler(2,5), sql(" and name=?"), "Tom" );
+ *
+ * In above examples connection and sqlHandlers are optional items, these
+ * optional items can appear at anywhere
+ *
+ * @param items SQL String / SQL Parameters / Connection / ResultSetHandler class
+ * or instance / SqlHandler class or instance
+ * @return a PreparedSQL instance
+ */
+ private PreparedSQL doPrepare(boolean inlineStyle, Object... items) {// NOSONAR
+ PreparedSQL ps = dealSqlItems(null, inlineStyle, items);
+ ps.addGlobalAndThreadedHandlers(this);
+ return ps;
+ }
+
+ /**
+ * Convert parameters to JDBC type, like java.util.Date to java.sql.Date
+ */
+ public void preparedParamsToJdbc(PreparedSQL ps) {
+ //empty method for child class override
+ }
+
+ /**
+ * Deal with multiple SqlItems
+ */
+ public PreparedSQL dealSqlItems(PreparedSQL lastPreSql, boolean inlineStyle, Object... items) {// NOSONAR
+ if (items == null || items.length == 0)
+ throw new DbProException("prepareSQL items can not be empty");
+ PreparedSQL predSQL = lastPreSql;
+ if (predSQL == null)
+ predSQL = new PreparedSQL();
+ for (Object item : items) {
+ if (item == null) {
+ if (inlineStyle)
+ throw new DbProException("null value can not append as SQL piece");
+ else
+ predSQL.addParam(null);
+ } else if (!dealOneSqlItem(inlineStyle, predSQL, item)) {
+ if (item instanceof SqlItem)
+ throw new DbProException("One SqlItem did not find explainer, type=" + ((SqlItem) item).getType());
+ if (item.getClass().isArray()) {
+ Object[] array = (Object[]) item;
+ if (array.length != 0)
+ dealSqlItems(predSQL, inlineStyle, (Object[]) item);
+ } else if (inlineStyle)
+ predSQL.addSql(item); // iXxxx style, unknown object look as SQL piece
+ else
+ predSQL.addParam(item); // pXxxx style, unknown object look as parameter
+ }
+ }
+ predSQL.setSql(predSQL.getSqlBuilder().toString());
+ return predSQL;
+ }
+
+ /**
+ * Here deal one SqlItem, if can deal it, return true, otherwise return false,
+ * subclass (like DbContext) can override this method
+ */
+ protected boolean dealOneSqlItem(boolean inlineStyle, PreparedSQL predSQL, Object item) {// NOSONAR
+ if (item instanceof String) {
+ predSQL.addSqlOrParam(inlineStyle, (String) item);
+ } else if (item instanceof PreparedSQL) {
+ PreparedSQL psItem = (PreparedSQL) item;
+ if (psItem.getSql() != null)
+ predSQL.addSql(psItem.getSql());
+ if (psItem.getParams() != null)
+ for (Object obj : psItem.getParams())
+ predSQL.addParam(obj);
+ } else if (item instanceof SqlTemplateEngine) {
+ predSQL.setTemplateEngine((SqlTemplateEngine) item);
+ } else if (item instanceof Map, ?>) {
+ predSQL.addTemplateMap((Map) item);
+ } else if (item instanceof SqlOption) {
+ if (SqlOption.USE_MASTER.equals(item)) {
+ predSQL.setMasterSlaveOption(SqlOption.USE_MASTER);
+ } else if (SqlOption.USE_SLAVE.equals(item)) {
+ predSQL.setMasterSlaveOption(SqlOption.USE_SLAVE);
+ } else if (SqlOption.USE_AUTO.equals(item)) {
+ predSQL.setMasterSlaveOption(SqlOption.USE_AUTO);
+ } else if (SqlOption.USE_BOTH.equals(item)) {
+ predSQL.setMasterSlaveOption(SqlOption.USE_BOTH);
+ } else if (SqlOption.EXECUTE.equals(item)) {
+ predSQL.setOperationType(SqlOption.EXECUTE);
+ } else if (SqlOption.UPDATE.equals(item)) {
+ predSQL.setOperationType(SqlOption.UPDATE);
+ } else if (SqlOption.QUERY.equals(item)) {
+ predSQL.setOperationType(SqlOption.QUERY);
+ } else if (SqlOption.INSERT.equals(item)) {
+ predSQL.setOperationType(SqlOption.INSERT);
+ } else
+ return false;
+ } else if (item instanceof SqlItem) {
+ SqlItem sqItem = (SqlItem) item;
+ SqlOption sqlItemType = sqItem.getType();
+ if (SqlOption.OTHER.equals(sqlItemType))
+ predSQL.addOther(sqItem);
+ else if (SqlOption.PARAM.equals(sqlItemType)) {
+ if (sqItem.getParameters() == null)
+ predSQL.addParam(null);
+ else for (Object pm : sqItem.getParameters())
+ predSQL.addParam(pm);
+ } else if (SqlOption.BIND.equals(sqlItemType)) {
+ predSQL.addTemplateParam(sqItem);
+ } else if (SqlOption.SQL.equals(sqlItemType)) {
+ for (Object pm : sqItem.getParameters())
+ predSQL.addSql(pm);
+ } else if (SqlOption.QUESTION_PARAM.equals(sqlItemType)) {
+ if (sqItem.getParameters() == null) {
+ predSQL.addParam(null);
+ predSQL.addSql("?");
+ } else {
+ int i = 0;
+ for (Object pm : sqItem.getParameters()) {
+ predSQL.addParam(pm);
+ if (i > 0)
+ predSQL.addSql(",");
+ predSQL.addSql("?");
+ i++;
+ }
+ }
+ } else if (SqlOption.VALUES_QUESTIONS.equals(sqlItemType)) {
+ predSQL.addSql(" values(");
+ for (int i = 0; i < predSQL.getParamSize(); i++) {
+ if (i > 0)
+ predSQL.addSql(",");
+ predSQL.addSql("?");
+ }
+ predSQL.addSql(")");
+ } else if (SqlOption.ENABLE_HANDLERS.equals(sqlItemType)) {
+ predSQL.enableAllHandlers();
+ } else if (SqlOption.DISABLE_HANDLERS.equals(sqlItemType)) {
+ predSQL.disableHandlers((Object[]) sqItem.getParameters());
+ } else if (SqlOption.SWITCHTO.equals(sqlItemType)) {
+ predSQL.setSwitchTo((DbPro) sqItem.getParameters()[0]);
+ } else if (SqlOption.TIMEOUT.equals(sqlItemType)) {
+ int seconds = 0;
+ if (sqItem.getParameters().length > 0) {
+ Object param = sqItem.getParameters()[0];
+ if (param instanceof Integer) {
+ seconds = Integer.parseInt(param.toString());
+ }
+ }
+ predSQL.setTimeoutSeconds(seconds);
+ } else
+ return false;
+ } else if (item instanceof Text)
+ predSQL.addSql(item.toString());
+ else if (item instanceof Connection)
+ predSQL.setConnection((Connection) item);
+ else if (item instanceof DbPro)
+ predSQL.setSwitchTo((DbPro) item);
+ else if (item instanceof SqlHandler)
+ predSQL.addHandler((SqlHandler) item);
+ else if (item instanceof ResultSetHandler)
+ predSQL.setResultSetHandler((ResultSetHandler) item);
+ else if (item instanceof Class) {
+ if (Text.class.isAssignableFrom((Class) item)) {
+ String text = Text.classToString((Class) item);
+ predSQL.addSqlOrParam(inlineStyle, text);
+ return true;
+ } else
+ return false;
+ } else if (item instanceof CustomizedSqlItem) {
+ ((CustomizedSqlItem) item).doPrepare(predSQL);
+ } else if (sqlItemHandler != null)
+ return sqlItemHandler.handle(predSQL, item);
+ else
+ return false;
+ return true;
+ }
+
+ public void ________3letter_inlineStyles________() {// NOSONAR
+ }
+
+ /**
+ * Executes the in-line style query statement
+ *
+ * @param inlineSQL the in-line style SQL
+ * @return An object generated by the handler.
+ */
+ public T qry(Object... inlineSQL) {
+ PreparedSQL ps = prepare(inlineSQL);
+ ps.ifNullSetType(SqlOption.QUERY);
+ return (T) runPreparedSQL(ps);
+ }
+
+ /**
+ * Execute an In-line style query for an Object, only return the first row and
+ * first column's value if more than one column or more than 1 rows returned
+ *
+ * @param inlineSQL
+ * @param params
+ * @return An Object or null value determined by SQL content
+ */
+ public T qryObject(Object... inlineSQL) {
+ PreparedSQL ps = prepare(inlineSQL);
+ ps.ifNullSetType(SqlOption.QUERY);
+ if (ps.getResultSetHandler() == null)
+ ps.setResultSetHandler(new ScalarHandler(1));
+ return (T) runPreparedSQL(ps);
+ }
+
+ /**
+ * In-line style execute query and force return a long value, runtime exception
+ * may throw if result can not be cast to long.
+ */
+ public long qryLongValue(Object... inlineSQL) {
+ return ((Number) qryObject(inlineSQL)).longValue();// NOSONAR
+ }
+
+ /**
+ * In-line style execute query and force return a int, runtime exception may
+ * throw if result can not be cast to int.
+ */
+ public int qryIntValue(Object... inlineSQL) {
+ return ((Number) qryObject(inlineSQL)).intValue();// NOSONAR
+ }
+
+ /**
* In-line style execute query and force return a boolean, runtime exception may
* throw if result can not be cast to boolean.
*/
public boolean qryBooleanValue(Object... inlineSQL) {
return (Boolean) qryObject(inlineSQL);// NOSONAR
}
-
-
- /**
- * In-line style execute query and force return a String object.
- */
- public String qryString(Object... inlineSQL) {
- Object result = qryObject(inlineSQL);
- return result == null ? null : result.toString();
- }
-
- /**
- * In-Line style execute query and force return a List> type
- * result.
- */
- public List> qryMapList(Object... items) {
- PreparedSQL ps = prepare(items);
- ps.addHandler(new MapListHandler());
- ps.ifNullSetType(SqlOption.QUERY);
- return (List>) runPreparedSQL(ps);
- }
-
- /**
- * In-Line style execute query and force return a Map type
- * result, if no record found, return empty HashMap instance;
- */
- public Map qryMap(Object... items) {
- List> list = qryMapList(items);
- if (list.isEmpty())
- return new HashMap();
- return list.get(0);
- }
-
- /**
- * In-Line style execute query and force return a Map type
- * result, if no record found, return empty HashMap instance;
- */
- public List qryList(Object... items) {
- return this.qry(new ColumnListHandler(1), items);
- }
-
-
- /**
- * Executes the in-line style INSERT, UPDATE, or DELETE statement
- *
- * @param inlineSQL
- * the in-line style SQL
- * @return The number of rows updated.
- */
- public int upd(Object... inlineSQL) {
- PreparedSQL ps = prepare(inlineSQL);
- ps.ifNullSetType(SqlOption.UPDATE);
- return (Integer) runPreparedSQL(ps);
- }
-
- /**
- * Executes the in-line style insert statement
- *
- * @param inlineSQL
- * the in-line style SQL
- * @return An object generated by the handler.
- */
- public T ins(Object... inlineSQL) {
- PreparedSQL ps = prepare(inlineSQL);
- ps.ifNullSetType(SqlOption.INSERT);
- return (T) runPreparedSQL(ps);
- }
-
- /**
- * Executes the in-line style execute statement
- *
- * @param inlineSQL
- * the in-line style SQL
- * @return A list of objects generated by the handler, or number of rows updated
- * if no handler
- */
- public T exe(Object... inlineSQL) {
- PreparedSQL ps = prepare(inlineSQL);
- ps.ifNullSetType(SqlOption.EXECUTE);
- return (T) runPreparedSQL(ps);
- }
-
- /**
- * nXxxx style series methods are design to replace QueryRunner's xxxx method,
- * the difference is nXxxx methods do not throw SqlException
- */
- public void ________jdbcMethods________() {// NOSONAR
-
- }
-
- /**
- * Query for an Object, only return the first row and first column's value if
- * more than one column or more than 1 rows returned, a null object may return
- * if no result found , DbProRuntimeException may be threw if some SQL operation
- * Exception happen.
- *
- * @param sql
- * @param params
- * @return An Object or null, Object type determined by SQL content
- */
- @Override
- public T jdbcQueryForObject(String sql, Object... params) {
- PreparedSQL ps = new PreparedSQL(SqlOption.QUERY, null, SingleTonHandlers.scalarHandler, sql, params);
- ps.addGlobalAndThreadedHandlers(this);
- return (T) runPreparedSQL(ps);
- }
-
- /**
- * Executes the given INSERT, UPDATE, or DELETE SQL statement.
- *
- * @param sql
- * the SQL
- * @param params
- * the parameters if have
- * @return The number of rows updated.
- */
- @Override
- public int jdbcUpdate(String sql, Object... params) {
- PreparedSQL ps = new PreparedSQL(SqlOption.UPDATE, null, null, sql, params);
- ps.addGlobalAndThreadedHandlers(this);
- return (Integer) runPreparedSQL(ps);
- }
-
- /**
- * Execute an statement, including a stored procedure call, which does not
- * return any result sets. Any parameters which are instances of
- * {@link OutParameter} will be registered as OUT parameters.
- *
- * Use this method when invoking a stored procedure with OUT parameters that
- * does not return any result sets.
- *
- * @param sql
- * the SQL
- * @return The number of rows updated.
- */
- @Override
- public int jdbcExecute(String sql, Object... params) {
- PreparedSQL ps = new PreparedSQL(SqlOption.EXECUTE, null, null, sql, params);
- ps.addGlobalAndThreadedHandlers(this);
- return (Integer) runPreparedSQL(ps);
- }
-
- // ============================================================================
+
+
+ /**
+ * In-line style execute query and force return a String object.
+ */
+ public String qryString(Object... inlineSQL) {
+ Object result = qryObject(inlineSQL);
+ return result == null ? null : result.toString();
+ }
+
+ /**
+ * In-Line style execute query and force return a List> type
+ * result.
+ */
+ public List> qryMapList(Object... items) {
+ PreparedSQL ps = prepare(items);
+ ps.addHandler(new MapListHandler());
+ ps.ifNullSetType(SqlOption.QUERY);
+ return (List>) runPreparedSQL(ps);
+ }
+
+ /**
+ * In-Line style execute query and force return a Map type
+ * result, if no record found, return empty HashMap instance;
+ */
+ public Map qryMap(Object... items) {
+ List> list = qryMapList(items);
+ if (list.isEmpty())
+ return new HashMap();
+ return list.get(0);
+ }
+
+ /**
+ * In-Line style execute query and force return a Map type
+ * result, if no record found, return empty HashMap instance;
+ */
+ public List qryList(Object... items) {
+ return this.qry(new ColumnListHandler(1), items);
+ }
+
+
+ /**
+ * Executes the in-line style INSERT, UPDATE, or DELETE statement
+ *
+ * @param inlineSQL the in-line style SQL
+ * @return The number of rows updated.
+ */
+ public int upd(Object... inlineSQL) {
+ PreparedSQL ps = prepare(inlineSQL);
+ ps.ifNullSetType(SqlOption.UPDATE);
+ return (Integer) runPreparedSQL(ps);
+ }
+
+ /**
+ * Executes the in-line style insert statement
+ *
+ * @param inlineSQL the in-line style SQL
+ * @return An object generated by the handler.
+ */
+ public T ins(Object... inlineSQL) {
+ PreparedSQL ps = prepare(inlineSQL);
+ ps.ifNullSetType(SqlOption.INSERT);
+ return (T) runPreparedSQL(ps);
+ }
+
+ /**
+ * Executes the in-line style execute statement
+ *
+ * @param inlineSQL the in-line style SQL
+ * @return A list of objects generated by the handler, or number of rows updated
+ * if no handler
+ */
+ public T exe(Object... inlineSQL) {
+ PreparedSQL ps = prepare(inlineSQL);
+ ps.ifNullSetType(SqlOption.EXECUTE);
+ return (T) runPreparedSQL(ps);
+ }
+
+ /**
+ * nXxxx style series methods are design to replace QueryRunner's xxxx method,
+ * the difference is nXxxx methods do not throw SqlException
+ */
+ public void ________jdbcMethods________() {// NOSONAR
+
+ }
+
+ /**
+ * Query for an Object, only return the first row and first column's value if
+ * more than one column or more than 1 rows returned, a null object may return
+ * if no result found , DbProRuntimeException may be threw if some SQL operation
+ * Exception happen.
+ *
+ * @param sql
+ * @param params
+ * @return An Object or null, Object type determined by SQL content
+ */
+ @Override
+ public T jdbcQueryForObject(String sql, Object... params) {
+ PreparedSQL ps = new PreparedSQL(SqlOption.QUERY, null, SingleTonHandlers.scalarHandler, sql, params);
+ ps.addGlobalAndThreadedHandlers(this);
+ return (T) runPreparedSQL(ps);
+ }
+
+ /**
+ * Executes the given INSERT, UPDATE, or DELETE SQL statement.
+ *
+ * @param sql the SQL
+ * @param params the parameters if have
+ * @return The number of rows updated.
+ */
+ @Override
+ public int jdbcUpdate(String sql, Object... params) {
+ PreparedSQL ps = new PreparedSQL(SqlOption.UPDATE, null, null, sql, params);
+ ps.addGlobalAndThreadedHandlers(this);
+ return (Integer) runPreparedSQL(ps);
+ }
+
+ /**
+ * Execute an statement, including a stored procedure call, which does not
+ * return any result sets. Any parameters which are instances of
+ * {@link OutParameter} will be registered as OUT parameters.
+ *
+ * Use this method when invoking a stored procedure with OUT parameters that
+ * does not return any result sets.
+ *
+ * @param sql the SQL
+ * @return The number of rows updated.
+ */
+ @Override
+ public int jdbcExecute(String sql, Object... params) {
+ PreparedSQL ps = new PreparedSQL(SqlOption.EXECUTE, null, null, sql, params);
+ ps.addGlobalAndThreadedHandlers(this);
+ return (Integer) runPreparedSQL(ps);
+ }
+
+ // ============================================================================
}
diff --git a/core/src/main/java/com/github/drinkjava2/jdbpro/ImprovedQueryRunner.java b/core/src/main/java/com/github/drinkjava2/jdbpro/ImprovedQueryRunner.java
index e2b5ab03c1f960d4821c01aa773a79b7e0c434ae..de6fc6bfc58f0b32a18aedae5c2af60eb3f4c903 100644
--- a/core/src/main/java/com/github/drinkjava2/jdbpro/ImprovedQueryRunner.java
+++ b/core/src/main/java/com/github/drinkjava2/jdbpro/ImprovedQueryRunner.java
@@ -556,14 +556,14 @@ public class ImprovedQueryRunner extends QueryRunner implements DataSourceHolder
try {
if (ps.getConnection() != null) {
if (ps.getParams() != null)
- return (T) query(ps.getConnection(), ps.getSql(), ps.getResultSetHandler(), ps.getParams());
+ return (T) query(ps.getConnection(), ps.getSql(),ps.getTimeoutSeconds(), ps.getResultSetHandler(), ps.getParams());
else
- return (T) query(ps.getConnection(), ps.getSql(), ps.getResultSetHandler());
+ return (T) query(ps.getConnection(), ps.getSql(),ps.getTimeoutSeconds(), ps.getResultSetHandler());
} else {
if (ps.getParams() != null)
- return (T) query(ps.getSql(), ps.getResultSetHandler(), ps.getParams());
+ return (T) query(ps.getSql(),ps.getTimeoutSeconds(), ps.getResultSetHandler(), ps.getParams());
else
- return (T) query(ps.getSql(), ps.getResultSetHandler());
+ return (T) query(ps.getSql(),ps.getTimeoutSeconds(), ps.getResultSetHandler());
}
} catch (SQLException e) {
throw new DbProException(e);
diff --git a/core/src/main/java/com/github/drinkjava2/jdbpro/PreparedSQL.java b/core/src/main/java/com/github/drinkjava2/jdbpro/PreparedSQL.java
index dffac98a9d6e1250b2d924999bdd7b0498966fbd..35216235e6568de60bf1f68c3bf43fcce86854fb 100644
--- a/core/src/main/java/com/github/drinkjava2/jdbpro/PreparedSQL.java
+++ b/core/src/main/java/com/github/drinkjava2/jdbpro/PreparedSQL.java
@@ -31,7 +31,7 @@ import com.github.drinkjava2.jdbpro.template.SqlTemplateEngine;
* PreparedSQL is a temporary object used for store SQL, parameter,
* ResultSetHandlers, SqlHandlers, Connection and templateEngine..., it's not
* thread-safe
- *
+ *
* @author Yong Zhu
* @since 1.7.0
*/
@@ -99,6 +99,8 @@ public class PreparedSQL {
/** EntityNet, this is designed for ORM program's EntityNet */
private Object entityNet = null;
+ /** query timeout secons default 0 unlimited*/
+ private int timeoutSeconds=0;
public PreparedSQL() {// default constructor
}
@@ -471,4 +473,11 @@ public class PreparedSQL {
this.ignoreEmpty = ignoreEmpty;
}
+ public int getTimeoutSeconds() {
+ return timeoutSeconds;
+ }
+
+ public void setTimeoutSeconds(int timeoutSeconds) {
+ this.timeoutSeconds = timeoutSeconds;
+ }
}
diff --git a/core/src/main/java/com/github/drinkjava2/jdbpro/SqlOption.java b/core/src/main/java/com/github/drinkjava2/jdbpro/SqlOption.java
index 186b05f2e5f5816475654f580ef300c86beb0b7c..4638ccf52025b152890fa0fe8f099d5e8c1852ff 100644
--- a/core/src/main/java/com/github/drinkjava2/jdbpro/SqlOption.java
+++ b/core/src/main/java/com/github/drinkjava2/jdbpro/SqlOption.java
@@ -18,7 +18,7 @@ package com.github.drinkjava2.jdbpro;
/**
* SqlOption system how to explain a SqlItem, SqlItem like "Message" in windows,
* SqlOption is the "Message" type.
- *
+ *
* @author Yong Zhu
* @since 1.7.0.3
*/
@@ -135,5 +135,7 @@ public enum SqlOption {
AUTO_SQL,
/** Mark a TAIL SqlItem, tell ORM to use this model do CRUD */
- TAIL
+ TAIL,
+ /** Mark a TAIL SqlItem, tell ORM to use query timeout throw exception */
+ TIMEOUT
}
\ No newline at end of file
diff --git a/core/src/main/java/com/github/drinkjava2/jsqlbox/DB.java b/core/src/main/java/com/github/drinkjava2/jsqlbox/DB.java
index 4bfe1813f92d16f8882408a21ef4f1513149f25b..356499e677243f609c9313ac1ad2f05496d7c9b1 100644
--- a/core/src/main/java/com/github/drinkjava2/jsqlbox/DB.java
+++ b/core/src/main/java/com/github/drinkjava2/jsqlbox/DB.java
@@ -31,7 +31,7 @@ import com.github.drinkjava2.jtransactions.TxResult;
/**
* DB store some public static methods, usually used for static import to
* simplify programming
- *
+ *
* @author Yong Zhu
* @since 1.0.8
*/
@@ -58,7 +58,7 @@ public abstract class DB {// NOSONAR
public static SqlItem par(Object... parameters) {
return new SqlItem(SqlOption.PARAM, parameters);
}
-
+
/**
* Cache parameters and return a "?" String
*/
@@ -70,14 +70,14 @@ public abstract class DB {// NOSONAR
public static SqlItem param(Object... parameters) {
return new SqlItem(SqlOption.PARAM, parameters);
}
-
+
/**
* Cache parameters and return a "?" String
*/
public static SqlItem ques(Object... parameters) {// NOSONAR
return new SqlItem(SqlOption.QUESTION_PARAM, parameters);
}
-
+
/**
* Cache parameters and return a "?" String
*/
@@ -85,6 +85,11 @@ public abstract class DB {// NOSONAR
return new SqlItem(SqlOption.QUESTION_PARAM, parameters);
}
+ /**
+ * Cache parameters and set querytimeout
+ */
+ public static SqlItem timeout(int seconds){return new SqlItem(SqlOption.TIMEOUT,seconds);}
+
/**
* If last param is not null, then add all items in SQL
* Example: query("select * from a where 1=1",notNull(" and name=?",name));
@@ -144,7 +149,7 @@ public abstract class DB {// NOSONAR
sb.append(items[i]);
return new Object[] {items[0], par(sb.toString())};
}
-
+
/** if condition true, return items array, else return "" */
public static Object when(boolean condition, Object... items) {
return condition ? items : "";
@@ -157,11 +162,11 @@ public abstract class DB {// NOSONAR
public static SqlItem valuesQuestions() {
return new SqlItem(SqlOption.VALUES_QUESTIONS);
}
-
+
public static SqlItem other(Object... otherInfos) {
return new SqlItem(SqlOption.OTHER, otherInfos);
}
-
+
public static List getOthers() {
return gctx().getOthers();
}
@@ -176,7 +181,7 @@ public abstract class DB {// NOSONAR
/**
* For tXxxx style templateEngine use, return a SqlItemType.PUT type SqlItem
* instance,
- *
+ *
* Usage: put("key1",value1,"key2",value2...);
*/
public static SqlItem bind(Object... parameters) {
@@ -190,17 +195,17 @@ public abstract class DB {// NOSONAR
public static SqlItem disableHandlers(Class>... args) {
return new SqlItem(SqlOption.DISABLE_HANDLERS, (Object[]) args);
}
-
+
//======================
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
/** Shortcut method equal to DbContext.getGlobalDbContext() */
public static DbContext gctx() {
return DbContext.getGlobalDbContext();
@@ -278,18 +283,18 @@ public abstract class DB {// NOSONAR
protected void ________Entity_Methods________() {// NOSONAR
}
- //@formatter:off
+ //@formatter:off
//Entity series methods from DbContext
-
+
public static List entityFind(Class entityClass, Object... items) {return gctx().entityFind(entityClass, items);}
public static List entityFindBySample(Object sampleBean, Object... items) {return gctx().entityFindBySample(sampleBean, items);}
public static List entityFindBySql(Object... items) {return gctx().entityFindBySql(items);}
- public static T entityFindOneBySQL(Object... items) {return gctx().entityFindOneBySQL(items);}
- public static T entityLoad(T entity, Object... items) {return gctx().entityLoad(entity, items);}
+ public static T entityFindOneBySQL(Object... items) {return gctx().entityFindOneBySQL(items);}
+ public static T entityLoad(T entity, Object... items) {return gctx().entityLoad(entity, items);}
public static T entityLoadById(Class entityClass, Object entityId, Object... items) {return gctx().entityLoadById(entityClass, entityId, items);}
public static T entityLoadByIdTry(Class entityClass, Object entityId, Object... items) {return gctx().entityLoadByIdTry(entityClass, entityId, items);}
public static T entityLoadBySql(Object... items) {return gctx().entityLoadBySql(items);}
- public static T entityInsert(T entity, Object... items) {return gctx().entityInsert(entity, items);}
+ public static T entityInsert(T entity, Object... items) {return gctx().entityInsert(entity, items);}
public static T entityUpdate(Object entity, Object... items) {return gctx().entityUpdate(entity, items);}
public static boolean entityExist(Object entity, Object... items) {return gctx().entityExist(entity, items);}
public static boolean entityExistById(Class> entityClass, Object id, Object... items) {return gctx().entityExistById(entityClass, id, items);}
@@ -304,12 +309,12 @@ public abstract class DB {// NOSONAR
public static List entityFindRelatedList(Object entityOrIterable, Object... sqlItems) {return gctx().entityFindRelatedList(entityOrIterable, sqlItems);}
public static Set entityFindRelatedSet(Object entity, Object... sqlItems) {return gctx().entityFindRelatedSet(entity, sqlItems);}
public static Map entityFindRelatedMap(Object entity, Object... sqlItems) {return gctx().entityFindRelatedMap(entity, sqlItems);}
- public static EntityNet autoNet(Class>... entityClass) {return gctx().autoNet(entityClass);}
-
-
- // simplilfied SQL methods
+ public static EntityNet autoNet(Class>... entityClass) {return gctx().autoNet(entityClass);}
+
+
+ // simplilfied SQL methods
protected void ________SQL_Methods________() {}// NOSONAR
-
+
public static T qry(Object... items) {return gctx().qry(items);}
public static T qryObject(Object... items) {return gctx().qryObject(items);}
public static long qryLongValue(Object... items) {return gctx().qryLongValue(items);}
@@ -324,5 +329,5 @@ public abstract class DB {// NOSONAR
public static List qryEntityList(Object... items) {return gctx().qryEntityList(items);}
public static PreparedSQL prepare(Object... items) { return gctx().prepare(items); }
-
+
}
\ No newline at end of file
diff --git a/core/src/main/java/org/apache/commons/dbutils/QueryRunner.java b/core/src/main/java/org/apache/commons/dbutils/QueryRunner.java
index 7f131f9094aeb95c0b0dcb38ef38ac4209897ef7..6533a0926c323c244b6d8ac46e2f91f236690cef 100644
--- a/core/src/main/java/org/apache/commons/dbutils/QueryRunner.java
+++ b/core/src/main/java/org/apache/commons/dbutils/QueryRunner.java
@@ -45,8 +45,8 @@ public class QueryRunner extends AbstractQueryRunner {
* Constructor for QueryRunner that controls the use of ParameterMetaData
.
*
* @param pmdKnownBroken Some drivers don't support {@link java.sql.ParameterMetaData#getParameterType(int) };
- * if pmdKnownBroken
is set to true, we won't even try it; if false, we'll try it,
- * and if it breaks, we'll remember not to use it again.
+ * if pmdKnownBroken
is set to true, we won't even try it; if false, we'll try it,
+ * and if it breaks, we'll remember not to use it again.
*/
public QueryRunner(boolean pmdKnownBroken) {
super(pmdKnownBroken);
@@ -54,7 +54,7 @@ public class QueryRunner extends AbstractQueryRunner {
/**
* Constructor for QueryRunner that takes a DataSource
to use.
- *
+ *
* Methods that do not take a Connection
parameter will retrieve connections from this
* DataSource
.
*
@@ -79,10 +79,10 @@ public class QueryRunner extends AbstractQueryRunner {
* Methods that do not take a Connection
parameter will retrieve connections from this
* DataSource
.
*
- * @param ds The DataSource
to retrieve connections from.
+ * @param ds The DataSource
to retrieve connections from.
* @param pmdKnownBroken Some drivers don't support {@link java.sql.ParameterMetaData#getParameterType(int) };
- * if pmdKnownBroken
is set to true, we won't even try it; if false, we'll try it,
- * and if it breaks, we'll remember not to use it again.
+ * if pmdKnownBroken
is set to true, we won't even try it; if false, we'll try it,
+ * and if it breaks, we'll remember not to use it again.
*/
public QueryRunner(DataSource ds, boolean pmdKnownBroken) {
super(ds, pmdKnownBroken);
@@ -90,11 +90,11 @@ public class QueryRunner extends AbstractQueryRunner {
/**
* Constructor for QueryRunner that takes a DataSource
to use and a StatementConfiguration
.
- *
+ *
* Methods that do not take a Connection
parameter will retrieve connections from this
* DataSource
.
*
- * @param ds The DataSource
to retrieve connections from.
+ * @param ds The DataSource
to retrieve connections from.
* @param stmtConfig The configuration to apply to statements when they are prepared.
*/
public QueryRunner(DataSource ds, StatementConfiguration stmtConfig) {
@@ -106,11 +106,11 @@ public class QueryRunner extends AbstractQueryRunner {
* controls the use of ParameterMetaData
. Methods that do not take a Connection
parameter
* will retrieve connections from this DataSource
.
*
- * @param ds The DataSource
to retrieve connections from.
+ * @param ds The DataSource
to retrieve connections from.
* @param pmdKnownBroken Some drivers don't support {@link java.sql.ParameterMetaData#getParameterType(int) };
- * if pmdKnownBroken
is set to true, we won't even try it; if false, we'll try it,
- * and if it breaks, we'll remember not to use it again.
- * @param stmtConfig The configuration to apply to statements when they are prepared.
+ * if pmdKnownBroken
is set to true, we won't even try it; if false, we'll try it,
+ * and if it breaks, we'll remember not to use it again.
+ * @param stmtConfig The configuration to apply to statements when they are prepared.
*/
public QueryRunner(DataSource ds, boolean pmdKnownBroken, StatementConfiguration stmtConfig) {
super(ds, pmdKnownBroken, stmtConfig);
@@ -119,11 +119,11 @@ public class QueryRunner extends AbstractQueryRunner {
/**
* Execute a batch of SQL INSERT, UPDATE, or DELETE queries.
*
- * @param conn The Connection to use to run the query. The caller is
- * responsible for closing this Connection.
- * @param sql The SQL to execute.
+ * @param conn The Connection to use to run the query. The caller is
+ * responsible for closing this Connection.
+ * @param sql The SQL to execute.
* @param params An array of query replacement parameters. Each row in
- * this array is one set of batch replacement values.
+ * this array is one set of batch replacement values.
* @return The number of rows updated per statement.
* @throws SQLException if a database access error occurs
* @since DbUtils 1.1
@@ -138,9 +138,9 @@ public class QueryRunner extends AbstractQueryRunner {
* set in the constructor. This Connection
must be in
* auto-commit mode or the update will not be saved.
*
- * @param sql The SQL to execute.
+ * @param sql The SQL to execute.
* @param params An array of query replacement parameters. Each row in
- * this array is one set of batch replacement values.
+ * this array is one set of batch replacement values.
* @return The number of rows updated per statement.
* @throws SQLException if a database access error occurs
* @since DbUtils 1.1
@@ -153,11 +153,12 @@ public class QueryRunner extends AbstractQueryRunner {
/**
* Calls update after checking the parameters to ensure nothing is null.
- * @param conn The connection to use for the batch call.
+ *
+ * @param conn The connection to use for the batch call.
* @param closeConn True if the connection should be closed, false otherwise.
- * @param sql The SQL statement to execute.
- * @param params An array of query replacement parameters. Each row in
- * this array is one set of batch replacement values.
+ * @param sql The SQL statement to execute.
+ * @param params An array of query replacement parameters. Each row in
+ * this array is one set of batch replacement values.
* @return The number of rows updated in the batch.
* @throws SQLException If there are database or parameter errors.
*/
@@ -192,7 +193,7 @@ public class QueryRunner extends AbstractQueryRunner {
rows = stmt.executeBatch();
} catch (SQLException e) {
- this.rethrow(e, sql, (Object[])params);
+ this.rethrow(e, sql, (Object[]) params);
} finally {
close(stmt);
if (closeConn) {
@@ -206,11 +207,12 @@ public class QueryRunner extends AbstractQueryRunner {
/**
* Execute an SQL SELECT query with a single replacement parameter. The
* caller is responsible for closing the connection.
- * @param The type of object that the handler returns
- * @param conn The connection to execute the query in.
- * @param sql The query to execute.
+ *
+ * @param The type of object that the handler returns
+ * @param conn The connection to execute the query in.
+ * @param sql The query to execute.
* @param param The replacement parameter.
- * @param rsh The handler that converts the results into an object.
+ * @param rsh The handler that converts the results into an object.
* @return The object returned by the handler.
* @throws SQLException if a database access error occurs
* @deprecated Use {@link #query(Connection, String, ResultSetHandler, Object...)}
@@ -223,14 +225,15 @@ public class QueryRunner extends AbstractQueryRunner {
/**
* Execute an SQL SELECT query with replacement parameters. The
* caller is responsible for closing the connection.
- * @param The type of object that the handler returns
- * @param conn The connection to execute the query in.
- * @param sql The query to execute.
+ *
+ * @param The type of object that the handler returns
+ * @param conn The connection to execute the query in.
+ * @param sql The query to execute.
* @param params The replacement parameters.
- * @param rsh The handler that converts the results into an object.
+ * @param rsh The handler that converts the results into an object.
* @return The object returned by the handler.
* @throws SQLException if a database access error occurs
- * @deprecated Use {@link #query(Connection,String,ResultSetHandler,Object...)} instead
+ * @deprecated Use {@link #query(Connection, String, ResultSetHandler, Object...)} instead
*/
@Deprecated
public T query(Connection conn, String sql, Object[] params, ResultSetHandler rsh) throws SQLException {
@@ -240,25 +243,44 @@ public class QueryRunner extends AbstractQueryRunner {
/**
* Execute an SQL SELECT query with replacement parameters. The
* caller is responsible for closing the connection.
- * @param The type of object that the handler returns
- * @param conn The connection to execute the query in.
- * @param sql The query to execute.
- * @param rsh The handler that converts the results into an object.
+ *
+ * @param The type of object that the handler returns
+ * @param conn The connection to execute the query in.
+ * @param sql The query to execute.
+ * @param rsh The handler that converts the results into an object.
* @param params The replacement parameters.
* @return The object returned by the handler.
* @throws SQLException if a database access error occurs
*/
public T query(Connection conn, String sql, ResultSetHandler rsh, Object... params) throws SQLException {
+ return query(conn, sql, 0, rsh, params);
+ }
+
+ /**
+ * Execute an SQL SELECT query with replacement parameters. The
+ * caller is responsible for closing the connection.
+ *
+ * @param The type of object that the handler returns
+ * @param conn The connection to execute the query in.
+ * @param sql The query to execute.
+ * @param timeout The query execute timeout.
+ * @param rsh The handler that converts the results into an object.
+ * @param params The replacement parameters.
+ * @return The object returned by the handler.
+ * @throws SQLException if a database access error occurs
+ */
+ public T query(Connection conn, String sql, int timeout, ResultSetHandler rsh, Object... params) throws SQLException {
return this.query(conn, false, sql, rsh, params);
}
/**
* Execute an SQL SELECT query without any replacement parameters. The
* caller is responsible for closing the connection.
- * @param The type of object that the handler returns
+ *
+ * @param The type of object that the handler returns
* @param conn The connection to execute the query in.
- * @param sql The query to execute.
- * @param rsh The handler that converts the results into an object.
+ * @param sql The query to execute.
+ * @param rsh The handler that converts the results into an object.
* @return The object returned by the handler.
* @throws SQLException if a database access error occurs
*/
@@ -270,12 +292,12 @@ public class QueryRunner extends AbstractQueryRunner {
* Executes the given SELECT SQL with a single replacement parameter.
* The Connection
is retrieved from the
* DataSource
set in the constructor.
- * @param The type of object that the handler returns
- * @param sql The SQL statement to execute.
- * @param param The replacement parameter.
- * @param rsh The handler used to create the result object from
- * the ResultSet
.
*
+ * @param The type of object that the handler returns
+ * @param sql The SQL statement to execute.
+ * @param param The replacement parameter.
+ * @param rsh The handler used to create the result object from
+ * the ResultSet
.
* @return An object generated by the handler.
* @throws SQLException if a database access error occurs
* @deprecated Use {@link #query(String, ResultSetHandler, Object...)}
@@ -291,14 +313,13 @@ public class QueryRunner extends AbstractQueryRunner {
* Executes the given SELECT SQL query and returns a result object.
* The Connection
is retrieved from the
* DataSource
set in the constructor.
- * @param The type of object that the handler returns
- * @param sql The SQL statement to execute.
- * @param params Initialize the PreparedStatement's IN parameters with
- * this array.
- *
- * @param rsh The handler used to create the result object from
- * the ResultSet
.
*
+ * @param The type of object that the handler returns
+ * @param sql The SQL statement to execute.
+ * @param params Initialize the PreparedStatement's IN parameters with
+ * this array.
+ * @param rsh The handler used to create the result object from
+ * the ResultSet
.
* @return An object generated by the handler.
* @throws SQLException if a database access error occurs
* @deprecated Use {@link #query(String, ResultSetHandler, Object...)}
@@ -314,30 +335,48 @@ public class QueryRunner extends AbstractQueryRunner {
* Executes the given SELECT SQL query and returns a result object.
* The Connection
is retrieved from the
* DataSource
set in the constructor.
- * @param The type of object that the handler returns
- * @param sql The SQL statement to execute.
- * @param rsh The handler used to create the result object from
- * the ResultSet
.
+ *
+ * @param The type of object that the handler returns
+ * @param sql The SQL statement to execute.
+ * @param rsh The handler used to create the result object from
+ * the ResultSet
.
* @param params Initialize the PreparedStatement's IN parameters with
- * this array.
+ * this array.
* @return An object generated by the handler.
* @throws SQLException if a database access error occurs
*/
public T query(String sql, ResultSetHandler rsh, Object... params) throws SQLException {
- Connection conn = this.prepareConnection();
- return this.query(conn, true, sql, rsh, params);
+ return query(sql,0,rsh,params);
}
+ /**
+ * Executes the given SELECT SQL query and returns a result object.
+ * The Connection
is retrieved from the
+ * DataSource
set in the constructor.
+ *
+ * @param The type of object that the handler returns
+ * @param sql The SQL statement to execute.
+ * @param rsh The handler used to create the result object from
+ * the ResultSet
.
+ * @param params Initialize the PreparedStatement's IN parameters with
+ * this array.
+ * @return An object generated by the handler.
+ * @throws SQLException if a database access error occurs
+ */
+ public T query(String sql,int timeout, ResultSetHandler rsh, Object... params) throws SQLException {
+ Connection conn = this.prepareConnection();
+ return this.query(conn, true, sql,timeout, rsh, params);
+ }
/**
* Executes the given SELECT SQL without any replacement parameters.
* The Connection
is retrieved from the
* DataSource
set in the constructor.
+ *
* @param The type of object that the handler returns
* @param sql The SQL statement to execute.
* @param rsh The handler used to create the result object from
- * the ResultSet
.
- *
+ * the ResultSet
.
* @return An object generated by the handler.
* @throws SQLException if a database access error occurs
*/
@@ -349,16 +388,34 @@ public class QueryRunner extends AbstractQueryRunner {
/**
* Calls query after checking the parameters to ensure nothing is null.
- * @param conn The connection to use for the query call.
+ *
+ * @param conn The connection to use for the query call.
* @param closeConn True if the connection should be closed, false otherwise.
- * @param sql The SQL statement to execute.
- * @param params An array of query replacement parameters. Each row in
- * this array is one set of batch replacement values.
+ * @param sql The SQL statement to execute.
+ * @param params An array of query replacement parameters. Each row in
+ * this array is one set of batch replacement values.
* @return The results of the query.
* @throws SQLException If there are database or parameter errors.
*/
private T query(Connection conn, boolean closeConn, String sql, ResultSetHandler rsh, Object... params)
throws SQLException {
+ return query(conn, closeConn, sql, 0, rsh, params);
+ }
+
+ /**
+ * Calls query after checking the parameters to ensure nothing is null.
+ *
+ * @param conn The connection to use for the query call.
+ * @param closeConn True if the connection should be closed, false otherwise.
+ * @param sql The SQL statement to execute.
+ * @param timeout The SQL statement to execute timeout.
+ * @param params An array of query replacement parameters. Each row in
+ * this array is one set of batch replacement values.
+ * @return The results of the query.
+ * @throws SQLException If there are database or parameter errors.
+ */
+ private T query(Connection conn, boolean closeConn, String sql, int timeout, ResultSetHandler rsh, Object... params)
+ throws SQLException {
if (conn == null) {
throw new SQLException("Null connection");
}
@@ -383,6 +440,9 @@ public class QueryRunner extends AbstractQueryRunner {
try {
stmt = this.prepareStatement(conn, sql);
+ if (timeout != 0) {
+ stmt.setQueryTimeout(timeout);
+ }
this.fillStatement(stmt, params);
rs = this.wrap(stmt.executeQuery());
result = rsh.handle(rs);
@@ -409,7 +469,7 @@ public class QueryRunner extends AbstractQueryRunner {
* parameters.
*
* @param conn The connection to use to run the query.
- * @param sql The SQL to execute.
+ * @param sql The SQL to execute.
* @return The number of rows updated.
* @throws SQLException if a database access error occurs
*/
@@ -421,8 +481,8 @@ public class QueryRunner extends AbstractQueryRunner {
* Execute an SQL INSERT, UPDATE, or DELETE query with a single replacement
* parameter.
*
- * @param conn The connection to use to run the query.
- * @param sql The SQL to execute.
+ * @param conn The connection to use to run the query.
+ * @param sql The SQL to execute.
* @param param The replacement parameter.
* @return The number of rows updated.
* @throws SQLException if a database access error occurs
@@ -434,8 +494,8 @@ public class QueryRunner extends AbstractQueryRunner {
/**
* Execute an SQL INSERT, UPDATE, or DELETE query.
*
- * @param conn The connection to use to run the query.
- * @param sql The SQL to execute.
+ * @param conn The connection to use to run the query.
+ * @param sql The SQL to execute.
* @param params The query replacement parameters.
* @return The number of rows updated.
* @throws SQLException if a database access error occurs
@@ -452,8 +512,8 @@ public class QueryRunner extends AbstractQueryRunner {
* not be saved.
*
* @param sql The SQL statement to execute.
- * @throws SQLException if a database access error occurs
* @return The number of rows updated.
+ * @throws SQLException if a database access error occurs
*/
public int update(String sql) throws SQLException {
Connection conn = this.prepareConnection();
@@ -468,10 +528,10 @@ public class QueryRunner extends AbstractQueryRunner {
* This Connection
must be in auto-commit mode or the
* update will not be saved.
*
- * @param sql The SQL statement to execute.
+ * @param sql The SQL statement to execute.
* @param param The replacement parameter.
- * @throws SQLException if a database access error occurs
* @return The number of rows updated.
+ * @throws SQLException if a database access error occurs
*/
public int update(String sql, Object param) throws SQLException {
Connection conn = this.prepareConnection();
@@ -485,11 +545,11 @@ public class QueryRunner extends AbstractQueryRunner {
* set in the constructor. This Connection
must be in
* auto-commit mode or the update will not be saved.
*
- * @param sql The SQL statement to execute.
+ * @param sql The SQL statement to execute.
* @param params Initializes the PreparedStatement's IN (i.e. '?')
- * parameters.
- * @throws SQLException if a database access error occurs
+ * parameters.
* @return The number of rows updated.
+ * @throws SQLException if a database access error occurs
*/
public int update(String sql, Object... params) throws SQLException {
Connection conn = this.prepareConnection();
@@ -499,11 +559,12 @@ public class QueryRunner extends AbstractQueryRunner {
/**
* Calls update after checking the parameters to ensure nothing is null.
- * @param conn The connection to use for the update call.
+ *
+ * @param conn The connection to use for the update call.
* @param closeConn True if the connection should be closed, false otherwise.
- * @param sql The SQL statement to execute.
- * @param params An array of update replacement parameters. Each row in
- * this array is one set of update replacement values.
+ * @param sql The SQL statement to execute.
+ * @param params An array of update replacement parameters. Each row in
+ * this array is one set of update replacement values.
* @return The number of rows updated.
* @throws SQLException If there are database or parameter errors.
*/
@@ -544,10 +605,11 @@ public class QueryRunner extends AbstractQueryRunner {
* Executes the given INSERT SQL without any replacement parameters.
* The Connection
is retrieved from the
* DataSource
set in the constructor.
+ *
* @param The type of object that the handler returns
* @param sql The SQL statement to execute.
* @param rsh The handler used to create the result object from
- * the ResultSet
of auto-generated keys.
+ * the ResultSet
of auto-generated keys.
* @return An object generated by the handler.
* @throws SQLException if a database access error occurs
* @since 1.6
@@ -561,10 +623,11 @@ public class QueryRunner extends AbstractQueryRunner {
* Connection
is retrieved from the DataSource
* set in the constructor. This Connection
must be in
* auto-commit mode or the insert will not be saved.
- * @param The type of object that the handler returns
- * @param sql The SQL statement to execute.
- * @param rsh The handler used to create the result object from
- * the ResultSet
of auto-generated keys.
+ *
+ * @param The type of object that the handler returns
+ * @param sql The SQL statement to execute.
+ * @param rsh The handler used to create the result object from
+ * the ResultSet
of auto-generated keys.
* @param params Initializes the PreparedStatement's IN (i.e. '?')
* @return An object generated by the handler.
* @throws SQLException if a database access error occurs
@@ -576,11 +639,12 @@ public class QueryRunner extends AbstractQueryRunner {
/**
* Execute an SQL INSERT query without replacement parameters.
- * @param The type of object that the handler returns
+ *
+ * @param The type of object that the handler returns
* @param conn The connection to use to run the query.
- * @param sql The SQL to execute.
- * @param rsh The handler used to create the result object from
- * the ResultSet
of auto-generated keys.
+ * @param sql The SQL to execute.
+ * @param rsh The handler used to create the result object from
+ * the ResultSet
of auto-generated keys.
* @return An object generated by the handler.
* @throws SQLException if a database access error occurs
* @since 1.6
@@ -591,11 +655,12 @@ public class QueryRunner extends AbstractQueryRunner {
/**
* Execute an SQL INSERT query.
- * @param The type of object that the handler returns
- * @param conn The connection to use to run the query.
- * @param sql The SQL to execute.
- * @param rsh The handler used to create the result object from
- * the ResultSet
of auto-generated keys.
+ *
+ * @param The type of object that the handler returns
+ * @param conn The connection to use to run the query.
+ * @param sql The SQL to execute.
+ * @param rsh The handler used to create the result object from
+ * the ResultSet
of auto-generated keys.
* @param params The query replacement parameters.
* @return An object generated by the handler.
* @throws SQLException if a database access error occurs
@@ -607,12 +672,13 @@ public class QueryRunner extends AbstractQueryRunner {
/**
* Executes the given INSERT SQL statement.
- * @param conn The connection to use for the query call.
+ *
+ * @param conn The connection to use for the query call.
* @param closeConn True if the connection should be closed, false otherwise.
- * @param sql The SQL statement to execute.
- * @param rsh The handler used to create the result object from
- * the ResultSet
of auto-generated keys.
- * @param params The query replacement parameters.
+ * @param sql The SQL statement to execute.
+ * @param rsh The handler used to create the result object from
+ * the ResultSet
of auto-generated keys.
+ * @param params The query replacement parameters.
* @return An object generated by the handler.
* @throws SQLException If there are database or parameter errors.
* @since 1.6
@@ -663,10 +729,11 @@ public class QueryRunner extends AbstractQueryRunner {
* Connection
is retrieved from the DataSource
* set in the constructor. This Connection
must be in
* auto-commit mode or the insert will not be saved.
- * @param The type of object that the handler returns
- * @param sql The SQL statement to execute.
- * @param rsh The handler used to create the result object from
- * the ResultSet
of auto-generated keys.
+ *
+ * @param The type of object that the handler returns
+ * @param sql The SQL statement to execute.
+ * @param rsh The handler used to create the result object from
+ * the ResultSet
of auto-generated keys.
* @param params Initializes the PreparedStatement's IN (i.e. '?')
* @return The result generated by the handler.
* @throws SQLException if a database access error occurs
@@ -678,11 +745,12 @@ public class QueryRunner extends AbstractQueryRunner {
/**
* Executes the given batch of INSERT SQL statements.
- * @param The type of object that the handler returns
- * @param conn The connection to use to run the query.
- * @param sql The SQL to execute.
- * @param rsh The handler used to create the result object from
- * the ResultSet
of auto-generated keys.
+ *
+ * @param The type of object that the handler returns
+ * @param conn The connection to use to run the query.
+ * @param sql The SQL to execute.
+ * @param rsh The handler used to create the result object from
+ * the ResultSet
of auto-generated keys.
* @param params The query replacement parameters.
* @return The result generated by the handler.
* @throws SQLException if a database access error occurs
@@ -694,12 +762,13 @@ public class QueryRunner extends AbstractQueryRunner {
/**
* Executes the given batch of INSERT SQL statements.
- * @param conn The connection to use for the query call.
+ *
+ * @param conn The connection to use for the query call.
* @param closeConn True if the connection should be closed, false otherwise.
- * @param sql The SQL statement to execute.
- * @param rsh The handler used to create the result object from
- * the ResultSet
of auto-generated keys.
- * @param params The query replacement parameters.
+ * @param sql The SQL statement to execute.
+ * @param rsh The handler used to create the result object from
+ * the ResultSet
of auto-generated keys.
+ * @param params The query replacement parameters.
* @return The result generated by the handler.
* @throws SQLException If there are database or parameter errors.
* @since 1.6
@@ -738,7 +807,7 @@ public class QueryRunner extends AbstractQueryRunner {
generatedKeys = rsh.handle(rs);
} catch (SQLException e) {
- this.rethrow(e, sql, (Object[])params);
+ this.rethrow(e, sql, (Object[]) params);
} finally {
close(stmt);
if (closeConn) {
@@ -762,8 +831,8 @@ public class QueryRunner extends AbstractQueryRunner {
* If the stored procedure returns result sets, use
* {@link #execute(java.sql.Connection, java.lang.String, org.apache.commons.dbutils.ResultSetHandler, java.lang.Object...) }.
*
- * @param conn The connection to use to run the query.
- * @param sql The SQL to execute.
+ * @param conn The connection to use to run the query.
+ * @param sql The SQL to execute.
* @param params The query replacement parameters.
* @return The number of rows updated.
* @throws SQLException if a database access error occurs
@@ -789,10 +858,10 @@ public class QueryRunner extends AbstractQueryRunner {
* set in the constructor. This Connection
must be in
* auto-commit mode or the update will not be saved.
*
- * @param sql The SQL statement to execute.
+ * @param sql The SQL statement to execute.
* @param params Initializes the CallableStatement's parameters (i.e. '?').
- * @throws SQLException if a database access error occurs
* @return The number of rows updated.
+ * @throws SQLException if a database access error occurs
*/
public int execute(String sql, Object... params) throws SQLException {
Connection conn = this.prepareConnection();
@@ -814,10 +883,10 @@ public class QueryRunner extends AbstractQueryRunner {
* {@link #execute(java.sql.Connection, java.lang.String, java.lang.Object...) }
* (if there are no result sets).
*
- * @param The type of object that the handler returns
- * @param conn The connection to use to run the query.
- * @param sql The SQL to execute.
- * @param rsh The result set handler
+ * @param The type of object that the handler returns
+ * @param conn The connection to use to run the query.
+ * @param sql The SQL to execute.
+ * @param rsh The result set handler
* @param params The query replacement parameters.
* @return A list of objects generated by the handler
* @throws SQLException if a database access error occurs
@@ -840,9 +909,9 @@ public class QueryRunner extends AbstractQueryRunner {
* {@link #execute(java.lang.String, java.lang.Object...) }
* (if there are no result sets).
*
- * @param The type of object that the handler returns
- * @param sql The SQL to execute.
- * @param rsh The result set handler
+ * @param The type of object that the handler returns
+ * @param sql The SQL to execute.
+ * @param rsh The result set handler
* @param params The query replacement parameters.
* @return A list of objects generated by the handler
* @throws SQLException if a database access error occurs
@@ -856,11 +925,12 @@ public class QueryRunner extends AbstractQueryRunner {
/**
* Invokes the stored procedure via update after checking the parameters to
* ensure nothing is null.
- * @param conn The connection to use for the update call.
+ *
+ * @param conn The connection to use for the update call.
* @param closeConn True if the connection should be closed, false otherwise.
- * @param sql The SQL statement to execute.
- * @param params An array of update replacement parameters. Each row in
- * this array is one set of update replacement values.
+ * @param sql The SQL statement to execute.
+ * @param params An array of update replacement parameters. Each row in
+ * this array is one set of update replacement values.
* @return The number of rows updated.
* @throws SQLException If there are database or parameter errors.
*/
@@ -902,12 +972,13 @@ public class QueryRunner extends AbstractQueryRunner {
/**
* Invokes the stored procedure via update after checking the parameters to
* ensure nothing is null.
- * @param conn The connection to use for the update call.
+ *
+ * @param conn The connection to use for the update call.
* @param closeConn True if the connection should be closed, false otherwise.
- * @param sql The SQL statement to execute.
- * @param rsh The result set handler
- * @param params An array of update replacement parameters. Each row in
- * this array is one set of update replacement values.
+ * @param sql The SQL statement to execute.
+ * @param rsh The result set handler
+ * @param params An array of update replacement parameters. Each row in
+ * this array is one set of update replacement values.
* @return List of all objects generated by the ResultSetHandler for all result sets handled.
* @throws SQLException If there are database or parameter errors.
*/
@@ -969,17 +1040,18 @@ public class QueryRunner extends AbstractQueryRunner {
* Set the value on all the {@link OutParameter} instances in the
* params
array using the OUT parameter values from the
* stmt
.
- * @param stmt the statement from which to retrieve OUT parameter values
+ *
+ * @param stmt the statement from which to retrieve OUT parameter values
* @param params the parameter array for the statement invocation
* @throws SQLException when the value could not be retrieved from the
- * statement.
+ * statement.
*/
@SuppressWarnings("rawtypes")
- private void retrieveOutParameters(CallableStatement stmt, Object[] params) throws SQLException {
+ private void retrieveOutParameters(CallableStatement stmt, Object[] params) throws SQLException {
if (params != null) {
for (int i = 0; i < params.length; i++) {
if (params[i] instanceof OutParameter) {
- ((OutParameter)params[i]).setValue(stmt, i + 1);
+ ((OutParameter) params[i]).setValue(stmt, i + 1);
}
}
}
diff --git a/core/src/test/java/com/github/drinkjava2/jsqlbox/helloworld/UsageAndSpeedTest.java b/core/src/test/java/com/github/drinkjava2/jsqlbox/helloworld/UsageAndSpeedTest.java
index e5fc8cb3056a56e18427cfb14ebbd1c0bd99e27c..777187403c0fc3d8bd57325c0fa2433a40c8c2c0 100644
--- a/core/src/test/java/com/github/drinkjava2/jsqlbox/helloworld/UsageAndSpeedTest.java
+++ b/core/src/test/java/com/github/drinkjava2/jsqlbox/helloworld/UsageAndSpeedTest.java
@@ -1,13 +1,5 @@
package com.github.drinkjava2.jsqlbox.helloworld;
-import static com.github.drinkjava2.jsqlbox.DB.TEMPLATE;
-import static com.github.drinkjava2.jsqlbox.DB.bind;
-import static com.github.drinkjava2.jsqlbox.DB.notNull;
-import static com.github.drinkjava2.jsqlbox.DB.par;
-import static com.github.drinkjava2.jsqlbox.DB.que;
-import static com.github.drinkjava2.jsqlbox.DB.valuesQuestions;
-import static com.github.drinkjava2.jsqlbox.DB.when;
-
import java.lang.reflect.Method;
import java.sql.Connection;
import java.sql.PreparedStatement;
@@ -34,491 +26,522 @@ import com.github.drinkjava2.jsqlbox.DB;
import com.github.drinkjava2.jsqlbox.DbContext;
import com.zaxxer.hikari.HikariDataSource;
+import static com.github.drinkjava2.jsqlbox.DB.*;
+
/**
* Usage of different SQL style and speed test
- *
+ *
* @author Yong Zhu
* @since 1.7.0
*/
public class UsageAndSpeedTest {
- static long REPEAT_TIMES = 1;
- static boolean PRINT_TIMEUSED = false;
-
- protected HikariDataSource dataSource;
-
- @Before
- public void init() {
- dataSource = new HikariDataSource();
- dataSource.setJdbcUrl("jdbc:h2:mem:DBName;MODE=MYSQL;DB_CLOSE_DELAY=-1;TRACE_LEVEL_SYSTEM_OUT=0");
- dataSource.setDriverClassName("org.h2.Driver");
- dataSource.setUsername("sa");// change to your user & password
- dataSource.setPassword("");
- DbContext ctx = new DbContext(dataSource);
- DbContext.resetGlobalVariants();
- for (String ddl : ctx.getDialect().toDropAndCreateDDL(UserAR.class))
- try {
- ctx.jdbcExecute(ddl);
- } catch (Exception e) {
- }
- }
-
- @After
- public void cleanUp() {
- dataSource.close();
- }
-
- @Test
- public void speedTest() throws Exception {
- try {
- PRINT_TIMEUSED = false;
- REPEAT_TIMES = 1;// warm up
- runTestMethods();
- PRINT_TIMEUSED = true;
- REPEAT_TIMES = 10;// Change to 10000 to do speed test
- System.out.println("Speed test, compare method execute time for repeat " + REPEAT_TIMES + " times:");
- runTestMethods();
- } finally {
- PRINT_TIMEUSED = false;
- REPEAT_TIMES = 1;
- }
- }
-
- private void runTestMethods() throws Exception {
- runMethod("pureJdbc");
- runMethod("withConnection");
- runMethod("oldDbutilsMethods");
- runMethod("simpleMethods");
- runMethod("templateStyle");
- runMethod("dataMapperStyle");
- runMethod("activeRecordStyle");
- runMethod("activeRecordDefaultContext");
- }
-
- public void runMethod(String methodName) throws Exception {
- long start = System.currentTimeMillis();
- Method m = ClassUtils.getMethod(this.getClass(), methodName);
- m.invoke(this);
- long end = System.currentTimeMillis();
- String timeused = "" + (end - start) / 1000 + "." + (end - start) % 1000;
- if (PRINT_TIMEUSED)
- System.out.println(String.format("%35s: %6s s", methodName, timeused));
- }
-
- @Table(name = "users")
- public static class UserPOJO {
- @Id
- String name;
- String address;
-
- public UserPOJO() {
- }
-
- public UserPOJO(String name, String address) {
- this.name = name;
- this.address = address;
- }
-
- public String getName() {
- return name;
- }
-
- public void setName(String name) {
- this.name = name;
- }
-
- public String getAddress() {
- return address;
- }
-
- public void setAddress(String address) {
- this.address = address;
- }
- }
-
- @Table(name = UserAR.TABLE)
- public static class UserAR extends ActiveRecord {
- public static final String TABLE = "users";
- public static final String NAME = "name";
- public static final String ADDRESS = "address";
-
- @Id
- @Column(name = "name")
- String name;
- String address;
- Integer age;
-
- public UserAR() {
- }
-
- public UserAR(String name, String address) {
- this.name = name;
- this.address = address;
- }
-
- public String getName() {
- return name;
- }
-
- public void setName(String name) {
- this.name = name;
- }
-
- public String getAddress() {
- return address;
- }
-
- public void setAddress(String address) {
- this.address = address;
- }
-
- public Integer getAge() {
- return age;
- }
-
- public void setAge(Integer age) {
- this.age = age;
- }
-
- }
-
- @Test
- public void pureJdbc() {
- for (int i = 0; i < REPEAT_TIMES; i++) {
- Connection conn = null;
- PreparedStatement pst = null;
- ResultSet rs = null;
- try {
- conn = dataSource.getConnection();
- pst = conn.prepareStatement("insert into users (name,address) values(?,?)");
- pst.setString(1, "Sam");
- pst.setString(2, "Canada");
- pst.execute();
- pst.close();
-
- pst = conn.prepareStatement("update users set name=?, address=?");
- pst.setString(1, "Tom");
- pst.setString(2, "China");
- pst.execute();
- pst.close();
-
- pst = conn.prepareStatement("select count(*) from users where name=? and address=?");
- pst.setString(1, "Tom");
- pst.setString(2, "China");
- rs = pst.executeQuery();
- rs.next();
- Assert.assertEquals(1L, rs.getLong(1));
-
- pst = conn.prepareStatement("delete from users where name=? or address=?");
- pst.setString(1, "Tom");
- pst.setString(2, "China");
- pst.execute();
- } catch (SQLException e) {
- throw new RuntimeException(e);
- } finally {
- if (rs != null)
- try {
- rs.close();
- } catch (SQLException e) {
- }
- if (pst != null)
- try {
- pst.close();
- } catch (SQLException e) {
- }
- if (conn != null)
- try {
- conn.close();
- } catch (SQLException e) {
- }
- }
- }
- }
-
- @Test
- public void withConnection() {
- DbContext ctx = new DbContext(dataSource);
- for (int i = 0; i < REPEAT_TIMES; i++) {
- Connection conn = null;
- try {
- conn = ctx.prepareConnection();
- ctx.execute(conn, "insert into users (name,address) values(?,?)", "Sam", "Canada");
- ctx.execute(conn, "update users set name=?, address=?", "Tom", "China");
- Assert.assertEquals(1L, ctx.queryForLongValue(conn,
- "select count(*) from users where name=? and address=?", "Tom", "China"));
- ctx.execute(conn, "delete from users where name=? or address=?", "Tom", "China");
- } catch (SQLException e) {
- Systemout.println("Exception found: " + e.getMessage());
- } finally {
- try {
- ctx.close(conn);
- } catch (SQLException e) {
- Systemout.println("Exception found: " + e.getMessage());
- }
- }
- }
- }
-
- @Test
- public void oldDbutilsMethods() {
- DbContext ctx = new DbContext(dataSource);
- for (int i = 0; i < REPEAT_TIMES; i++) {
- try {
- ctx.execute("insert into users (name,address) values(?,?)", "Sam", "Canada");
- ctx.execute("update users set name=?, address=?", "Tom", "China");
- Assert.assertEquals(1L,
- ctx.queryForLongValue("select count(*) from users where name=? and address=?", "Tom", "China"));
- ctx.execute("delete from users where name=? or address=?", "Tom", "China");
- } catch (SQLException e) {
- Systemout.println("Exception found: " + e.getMessage());
- }
- }
- }
-
- @Test
- public void simpleMethods() {
- DbContext ctx = new DbContext(dataSource);
- for (int i = 0; i < REPEAT_TIMES; i++) {
- ctx.exe("insert into users (", //
- notNull(" name ,", "Sam"), //
- notNull(" someother ,", null), //
- " address ", par("Canada"), //
- ") ", valuesQuestions());
- ctx.exe("update users set name=?,address=?", par("Tom", "China"));
- Assert.assertEquals(1L, ctx.qryLongValue("select count(*) from users where name=? and address=?",
- par("Tom", "China")));
- ctx.exe("delete from users where name=", que("Tom"), " or address=", que("China"));
- }
- }
-
- @Test
- public void templateStyle() {
- DbContext ctx2 = new DbContext(dataSource);
- Map paramMap = new HashMap();
- for (int i = 0; i < REPEAT_TIMES; i++) {
- UserAR sam = new UserAR("Sam", "Canada");
- UserAR tom = new UserAR("Tom", "China");
- paramMap.put("user", sam);
- ctx2.exe(TEMPLATE, "insert into users (name, address) values(#{user.name},:user.address)", paramMap);
- ctx2.exe(TEMPLATE,"update users set name=#{user.name}, address=:user.address", bind("user", tom));
- Assert.assertEquals(1L,
- ctx2.qryLongValue(TEMPLATE,"select count(*) from users where name=#{name} and address=:addr",
- bind("name", "Tom", "addr", "China")));
- ctx2.exe(TEMPLATE,"delete from users where "//
- , " name=:name ", bind("name", "Tom")//
- , " or address=#{address}", bind("address", "China")//
- );
- }
- }
-
- @Test
- public void dataMapperStyle() {
- DbContext ctx = new DbContext(dataSource);
- for (int i = 0; i < REPEAT_TIMES; i++) {
- UserPOJO user = new UserPOJO();
- user.setName("Sam");
- user.setAddress("Canada");
- ctx.entityInsert(user);
- user.setAddress("China");
- ctx.entityUpdateTry(user);
- UserPOJO sam2 = ctx.entityLoadById(UserPOJO.class, "Sam");
- ctx.entityDeleteTry(sam2);
- }
- }
-
- @Test
- public void activeRecordStyle() {
- DbContext ctx = new DbContext(dataSource);
- UserAR user = new UserAR();
- for (int i = 0; i < REPEAT_TIMES; i++) {
- user.setName("Sam");
- user.setAddress("Canada");
- user.insert(ctx);
- user.setAddress("China");
- user.update(ctx);
- UserAR user2 = new UserAR().loadById("Sam",ctx);
- user2.delete(ctx);
- }
- }
-
- @Test
- public void activeRecordDefaultContext() {
- DbContext ctx = new DbContext(dataSource);
- DbContext.setGlobalDbContext(ctx);// use global default context
- UserAR user = new UserAR();
- for (int i = 0; i < REPEAT_TIMES; i++) {
- user.setName("Sam");
- user.setAddress("Canada");
- user.insert();
- user.setAddress("China");
- user.update();
- UserAR user2 = ctx.entityLoadById(UserAR.class, "Sam");
- user2.delete();
- }
- }
-
- protected void BelowNotForSpeedTest_JustDoSomeUnitTest__________________() {
- // below methods are for unit test only, not for speed test
- }
-
- @Test
- public void useAnotherSqlTemplateEngine() {
- DbContext ctx = new DbContext(dataSource);
- SqlTemplateEngine engine=new BasicSqlTemplate("[", "]", true, true);//default engine, change to use [] for param
- UserAR user = new UserAR("Sam", "Canada");
- UserAR tom = new UserAR("Tom", "China");
- ctx.exe(engine,"insert into users (name, address) values([user.name], [user.address])", bind("user", user));
- ctx.exe(engine,"update users set name=[user.name], address=[user.address]", bind("user", tom));
- Assert.assertEquals(1L,
- ctx.qryLongValue(engine,"select count(*) from users where ${col}= [name] and address=[addr]",
- bind("name", "Tom"), bind("addr", "China"), bind("$col", "name")));
- ctx.exe(engine,"delete from users where ${nm}='${t.name}' or address=:u.address", bind("u", tom), bind("$t", tom),
- bind("$nm", "name"));
- }
-
- @Test
- public void changeTemplateEngine() {
- DbContext ctx = new DbContext(dataSource);
- SqlTemplateEngine customizedEngine = new BasicSqlTemplate("[", "]", true, true);//customized sql engine
- UserAR user = new UserAR("Sam", "Canada");
- UserAR tom = new UserAR("Tom", "China");
- //default template
- ctx.exe(DB.TEMPLATE,"insert into users (name, address) values(#{user.name}, #{user.address})", bind("user", user));
- List lst=ctx.qryEntityList(TEMPLATE, UserPOJO.class, "select t.* from users t where t.name=:name", bind("name", "Sam"));
- Assert.assertEquals(1, lst.size());
-
- //below are customized engine
- ctx.exe(customizedEngine, "update users set name=[user.name], address=[user.address]", bind("user", tom));
- Assert.assertEquals(1L,
- ctx.qryLongValue(customizedEngine, "select count(*) from users where ${col}= [name] and address=[addr]",
- bind("name", "Tom"), bind("addr", "China"), bind("$col", "name")));
- ctx.exe("delete from users where ${nm}='${t.name}' or address=:u.address", bind("u", tom), bind("$t", tom),
- bind("$nm", "name"),customizedEngine);
- }
-
- /** Use const String can make SQL support Java Bean field refactoring */
- @Test
- public void supportRefactor() {
- DbContext ctx = new DbContext(dataSource);
- ctx.exe("insert into ", UserAR.TABLE, " ( ", //
- UserAR.NAME, ",", par("Sam"), //
- UserAR.ADDRESS, " ", par("Canada"), //
- ") ", valuesQuestions());
- ctx.exe("delete from users where ", //
- UserAR.NAME, "=", que("Sam"), //
- " or ", UserAR.ADDRESS, "=", que("Canada")//
- );
- }
-
- @Test
- public void activeRecordLoadByIdMap() {
- DbContext ctx = new DbContext(dataSource);
- UserAR user = new UserAR();
- user.useContext(ctx); // Use ctx as DbContext
- user.setName("Sam");
- user.setAddress("Canada");
- user.insert();
- user.setAddress("China");
- user.update();
- Map map = new HashMap();
- map.put("name", "Sam");
- UserAR user2 = new UserAR().useContext(ctx).loadById(map);
- user2.delete(ctx);
- }
-
- @Test
- public void activeRecordLoadByQuery() {
- DbContext ctx = new DbContext(dataSource);
- UserAR user = new UserAR();
- user.useContext(ctx); // Use ctx as DbContext
- user.setName("Sam");
- user.setAddress("Canada");
- user.insert();
- UserAR user2 = new UserAR().useContext(ctx).loadById(user.getName());
- Assert.assertEquals("Canada", user2.getAddress());
- }
-
- @Test
- public void dataMapperCrudTest() {
- DbContext ctx = new DbContext(dataSource);
- // ctx.setAllowShowSQL(true);
- UserAR user = new UserAR();
- for (int i = 1; i <= 10; i++) {
- user.setName("Tom" + i);
- user.setAddress("China" + i);
- ctx.entityInsert(user);
- }
- user = new UserAR();
- user.setName("Tom8");
- ctx.entityLoad(user);
- Assert.assertEquals("China8", user.getAddress());
-
- user = ctx.entityLoadById(UserAR.class, "Tom7");
- Assert.assertEquals("China7", user.getAddress());
-
- user.setAddress("Canada");
- ctx.entityUpdateTry(user);
- Assert.assertEquals("Canada", ctx.entityLoadById(UserAR.class, "Tom7").getAddress());
-
- ctx.entityDeleteTry(user);
- ctx.entityDeleteTry(user, " or name=?", par("Tom2"));
-
- Assert.assertEquals(7, ctx.entityFind(UserAR.class, " where name>?", par("Tom1")).size());
- }
-
- @Test
- public void conditionsQuery() {
- DbContext ctx = new DbContext(dataSource);
- ctx.setAllowShowSQL(true);
- final String name = "Tom";
- final String age = null;
- final String address = "China";
- ctx.exe("insert into users (", //
- notNull(" name", name), //
- notNull(" ,age ", age), //
- " ,address ", par(address), //
- ") ", valuesQuestions());
- ctx.exe("update users set ", //
- notNull(" name", "=", "?, ", name), //
- notNull(" age=?,", age), //
- " address=? ", par(address), //
- " where name is not null"//
- );
- Assert.assertEquals(1L, ctx.qryLongValue(//
- "select count(*) from users where 1=1 ", //
- notNull(" and name=? ", name), //
- "Tom".equals(name) ? ctx.prepare(" and name=? ", par(name)) : "", //
- "China".equals(address) ? new Object[] {" and address= ", que(address)} : "",//
- " order by name"
- ));
- ctx.jdbcExecute("delete from users");
- }
-
- @Test
- public void conditionsQuery2() { //use "when" method to test
- DbContext ctx = new DbContext(dataSource);
- ctx.setAllowShowSQL(true);
- final String name = "Tom";
- final String age = null;
- final String address = "China";
- ctx.exe("insert into users (", //
- " name", par(name), //
- when(age!=null," ,age ", par(age)), //
- " ,address ", par(address), //
- ") ", valuesQuestions());
- ctx.exe("update users set ", //
- " name=", que(name), //
- when(age!=null, ", age=", que(age)), //
- when(address!=null, ", address=", que(address)), //
- " where name is not null"
- );
- Assert.assertEquals(1L, ctx.qryLongValue(//
- "select count(*) from users where 1=1 ", //
- when(name!=null," and name=", que(name)),//
- when("Tom".equals(name)," and name=", que(name)),//
- when("China".equals(address)," and address=", que(address)),//
- " order by name"
- ));
- ctx.jdbcExecute("delete from users");
- }
-
+ static long REPEAT_TIMES = 1;
+ static boolean PRINT_TIMEUSED = false;
+
+ protected HikariDataSource dataSource;
+
+ @Before
+ public void init() {
+ dataSource = new HikariDataSource();
+ dataSource.setJdbcUrl("jdbc:h2:mem:DBName;MODE=MYSQL;DB_CLOSE_DELAY=-1;TRACE_LEVEL_SYSTEM_OUT=0");
+ dataSource.setDriverClassName("org.h2.Driver");
+ dataSource.setUsername("sa");// change to your user & password
+ dataSource.setPassword("");
+ DbContext ctx = new DbContext(dataSource);
+ DbContext.resetGlobalVariants();
+ for (String ddl : ctx.getDialect().toDropAndCreateDDL(UserAR.class))
+ try {
+ ctx.jdbcExecute(ddl);
+ } catch (Exception e) {
+ }
+ }
+
+ @After
+ public void cleanUp() {
+ dataSource.close();
+ }
+
+ @Test
+ public void speedTest() throws Exception {
+ try {
+ PRINT_TIMEUSED = false;
+ REPEAT_TIMES = 1;// warm up
+ runTestMethods();
+ PRINT_TIMEUSED = true;
+ REPEAT_TIMES = 10;// Change to 10000 to do speed test
+ System.out.println("Speed test, compare method execute time for repeat " + REPEAT_TIMES + " times:");
+ runTestMethods();
+ } finally {
+ PRINT_TIMEUSED = false;
+ REPEAT_TIMES = 1;
+ }
+ }
+
+ private void runTestMethods() throws Exception {
+ runMethod("pureJdbc");
+ runMethod("withConnection");
+ runMethod("oldDbutilsMethods");
+ runMethod("simpleMethods");
+ runMethod("templateStyle");
+ runMethod("dataMapperStyle");
+ runMethod("activeRecordStyle");
+ runMethod("activeRecordDefaultContext");
+ }
+
+ public void runMethod(String methodName) throws Exception {
+ long start = System.currentTimeMillis();
+ Method m = ClassUtils.getMethod(this.getClass(), methodName);
+ m.invoke(this);
+ long end = System.currentTimeMillis();
+ String timeused = "" + (end - start) / 1000 + "." + (end - start) % 1000;
+ if (PRINT_TIMEUSED)
+ System.out.println(String.format("%35s: %6s s", methodName, timeused));
+ }
+
+ @Table(name = "users")
+ public static class UserPOJO {
+ @Id
+ String name;
+ String address;
+
+ public UserPOJO() {
+ }
+
+ public UserPOJO(String name, String address) {
+ this.name = name;
+ this.address = address;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getAddress() {
+ return address;
+ }
+
+ public void setAddress(String address) {
+ this.address = address;
+ }
+ }
+
+ @Table(name = UserAR.TABLE)
+ public static class UserAR extends ActiveRecord {
+ public static final String TABLE = "users";
+ public static final String NAME = "name";
+ public static final String ADDRESS = "address";
+
+ @Id
+ @Column(name = "name")
+ String name;
+ String address;
+ Integer age;
+
+ public UserAR() {
+ }
+
+ public UserAR(String name, String address) {
+ this.name = name;
+ this.address = address;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getAddress() {
+ return address;
+ }
+
+ public void setAddress(String address) {
+ this.address = address;
+ }
+
+ public Integer getAge() {
+ return age;
+ }
+
+ public void setAge(Integer age) {
+ this.age = age;
+ }
+
+ }
+
+ @Test
+ public void pureJdbc() {
+ for (int i = 0; i < REPEAT_TIMES; i++) {
+ Connection conn = null;
+ PreparedStatement pst = null;
+ ResultSet rs = null;
+ try {
+ conn = dataSource.getConnection();
+ pst = conn.prepareStatement("insert into users (name,address) values(?,?)");
+ pst.setString(1, "Sam");
+ pst.setString(2, "Canada");
+ pst.execute();
+ pst.close();
+
+ pst = conn.prepareStatement("update users set name=?, address=?");
+ pst.setString(1, "Tom");
+ pst.setString(2, "China");
+ pst.execute();
+ pst.close();
+
+ pst = conn.prepareStatement("select count(*) from users where name=? and address=?");
+ pst.setString(1, "Tom");
+ pst.setString(2, "China");
+ rs = pst.executeQuery();
+ rs.next();
+ Assert.assertEquals(1L, rs.getLong(1));
+
+ pst = conn.prepareStatement("delete from users where name=? or address=?");
+ pst.setString(1, "Tom");
+ pst.setString(2, "China");
+ pst.execute();
+ } catch (SQLException e) {
+ throw new RuntimeException(e);
+ } finally {
+ if (rs != null)
+ try {
+ rs.close();
+ } catch (SQLException e) {
+ }
+ if (pst != null)
+ try {
+ pst.close();
+ } catch (SQLException e) {
+ }
+ if (conn != null)
+ try {
+ conn.close();
+ } catch (SQLException e) {
+ }
+ }
+ }
+ }
+
+ @Test
+ public void withConnection() {
+ DbContext ctx = new DbContext(dataSource);
+ for (int i = 0; i < REPEAT_TIMES; i++) {
+ Connection conn = null;
+ try {
+ conn = ctx.prepareConnection();
+ ctx.execute(conn, "insert into users (name,address) values(?,?)", "Sam", "Canada");
+ ctx.execute(conn, "update users set name=?, address=?", "Tom", "China");
+ Assert.assertEquals(1L, ctx.queryForLongValue(conn,
+ "select count(*) from users where name=? and address=?", "Tom", "China"));
+ ctx.execute(conn, "delete from users where name=? or address=?", "Tom", "China");
+ } catch (SQLException e) {
+ Systemout.println("Exception found: " + e.getMessage());
+ } finally {
+ try {
+ ctx.close(conn);
+ } catch (SQLException e) {
+ Systemout.println("Exception found: " + e.getMessage());
+ }
+ }
+ }
+ }
+
+ @Test
+ public void oldDbutilsMethods() {
+ DbContext ctx = new DbContext(dataSource);
+ for (int i = 0; i < REPEAT_TIMES; i++) {
+ try {
+ ctx.execute("insert into users (name,address) values(?,?)", "Sam", "Canada");
+ ctx.execute("update users set name=?, address=?", "Tom", "China");
+ Assert.assertEquals(1L,
+ ctx.queryForLongValue("select count(*) from users where name=? and address=?", "Tom", "China"));
+ ctx.execute("delete from users where name=? or address=?", "Tom", "China");
+ } catch (SQLException e) {
+ Systemout.println("Exception found: " + e.getMessage());
+ }
+ }
+ }
+
+ @Test
+ public void simpleMethods() {
+ DbContext ctx = new DbContext(dataSource);
+ for (int i = 0; i < REPEAT_TIMES; i++) {
+ ctx.exe("insert into users (", //
+ notNull(" name ,", "Sam"), //
+ notNull(" someother ,", null), //
+ " address ", par("Canada"), //
+ ") ", valuesQuestions());
+ ctx.exe("update users set name=?,address=?", par("Tom", "China"));
+ Assert.assertEquals(1L, ctx.qryLongValue("select count(*) from users where name=? and address=?",
+ par("Tom", "China")));
+ ctx.exe("delete from users where name=", que("Tom"), " or address=", que("China"));
+ }
+ }
+
+ @Test
+ public void templateStyle() {
+ DbContext ctx2 = new DbContext(dataSource);
+ Map paramMap = new HashMap();
+ for (int i = 0; i < REPEAT_TIMES; i++) {
+ UserAR sam = new UserAR("Sam", "Canada");
+ UserAR tom = new UserAR("Tom", "China");
+ paramMap.put("user", sam);
+ ctx2.exe(TEMPLATE, "insert into users (name, address) values(#{user.name},:user.address)", paramMap);
+ ctx2.exe(TEMPLATE, "update users set name=#{user.name}, address=:user.address", bind("user", tom));
+ Assert.assertEquals(1L,
+ ctx2.qryLongValue(TEMPLATE, "select count(*) from users where name=#{name} and address=:addr",
+ bind("name", "Tom", "addr", "China")));
+ ctx2.exe(TEMPLATE, "delete from users where "//
+ , " name=:name ", bind("name", "Tom")//
+ , " or address=#{address}", bind("address", "China")//
+ );
+ }
+ }
+
+ @Test
+ public void dataMapperStyle() {
+ DbContext ctx = new DbContext(dataSource);
+ for (int i = 0; i < REPEAT_TIMES; i++) {
+ UserPOJO user = new UserPOJO();
+ user.setName("Sam");
+ user.setAddress("Canada");
+ ctx.entityInsert(user);
+ user.setAddress("China");
+ ctx.entityUpdateTry(user);
+ UserPOJO sam2 = ctx.entityLoadById(UserPOJO.class, "Sam");
+ ctx.entityDeleteTry(sam2);
+ }
+ }
+
+ @Test
+ public void activeRecordStyle() {
+ DbContext ctx = new DbContext(dataSource);
+ UserAR user = new UserAR();
+ for (int i = 0; i < REPEAT_TIMES; i++) {
+ user.setName("Sam");
+ user.setAddress("Canada");
+ user.insert(ctx);
+ user.setAddress("China");
+ user.update(ctx);
+ UserAR user2 = new UserAR().loadById("Sam", ctx);
+ user2.delete(ctx);
+ }
+ }
+
+ @Test
+ public void activeRecordDefaultContext() {
+ DbContext ctx = new DbContext(dataSource);
+ DbContext.setGlobalDbContext(ctx);// use global default context
+ UserAR user = new UserAR();
+ for (int i = 0; i < REPEAT_TIMES; i++) {
+ user.setName("Sam");
+ user.setAddress("Canada");
+ user.insert();
+ user.setAddress("China");
+ user.update();
+ UserAR user2 = ctx.entityLoadById(UserAR.class, "Sam");
+ user2.delete();
+ }
+ }
+
+ protected void BelowNotForSpeedTest_JustDoSomeUnitTest__________________() {
+ // below methods are for unit test only, not for speed test
+ }
+
+ @Test
+ public void useAnotherSqlTemplateEngine() {
+ DbContext ctx = new DbContext(dataSource);
+ SqlTemplateEngine engine = new BasicSqlTemplate("[", "]", true, true);//default engine, change to use [] for param
+ UserAR user = new UserAR("Sam", "Canada");
+ UserAR tom = new UserAR("Tom", "China");
+ ctx.exe(engine, "insert into users (name, address) values([user.name], [user.address])", bind("user", user));
+ ctx.exe(engine, "update users set name=[user.name], address=[user.address]", bind("user", tom));
+ Assert.assertEquals(1L,
+ ctx.qryLongValue(engine, "select count(*) from users where ${col}= [name] and address=[addr]",
+ bind("name", "Tom"), bind("addr", "China"), bind("$col", "name")));
+ ctx.exe(engine, "delete from users where ${nm}='${t.name}' or address=:u.address", bind("u", tom), bind("$t", tom),
+ bind("$nm", "name"));
+ }
+
+ @Test
+ public void changeTemplateEngine() {
+ DbContext ctx = new DbContext(dataSource);
+ SqlTemplateEngine customizedEngine = new BasicSqlTemplate("[", "]", true, true);//customized sql engine
+ UserAR user = new UserAR("Sam", "Canada");
+ UserAR tom = new UserAR("Tom", "China");
+ //default template
+ ctx.exe(DB.TEMPLATE, "insert into users (name, address) values(#{user.name}, #{user.address})", bind("user", user));
+ List lst = ctx.qryEntityList(TEMPLATE, UserPOJO.class, "select t.* from users t where t.name=:name", bind("name", "Sam"));
+ Assert.assertEquals(1, lst.size());
+
+ //below are customized engine
+ ctx.exe(customizedEngine, "update users set name=[user.name], address=[user.address]", bind("user", tom));
+ Assert.assertEquals(1L,
+ ctx.qryLongValue(customizedEngine, "select count(*) from users where ${col}= [name] and address=[addr]",
+ bind("name", "Tom"), bind("addr", "China"), bind("$col", "name")));
+ ctx.exe("delete from users where ${nm}='${t.name}' or address=:u.address", bind("u", tom), bind("$t", tom),
+ bind("$nm", "name"), customizedEngine);
+ }
+
+ /**
+ * Use const String can make SQL support Java Bean field refactoring
+ */
+ @Test
+ public void supportRefactor() {
+ DbContext ctx = new DbContext(dataSource);
+ ctx.exe("insert into ", UserAR.TABLE, " ( ", //
+ UserAR.NAME, ",", par("Sam"), //
+ UserAR.ADDRESS, " ", par("Canada"), //
+ ") ", valuesQuestions());
+ ctx.exe("delete from users where ", //
+ UserAR.NAME, "=", que("Sam"), //
+ " or ", UserAR.ADDRESS, "=", que("Canada")//
+ );
+ }
+
+ @Test
+ public void activeRecordLoadByIdMap() {
+ DbContext ctx = new DbContext(dataSource);
+ UserAR user = new UserAR();
+ user.useContext(ctx); // Use ctx as DbContext
+ user.setName("Sam");
+ user.setAddress("Canada");
+ user.insert();
+ user.setAddress("China");
+ user.update();
+ Map map = new HashMap();
+ map.put("name", "Sam");
+ UserAR user2 = new UserAR().useContext(ctx).loadById(map);
+ user2.delete(ctx);
+ }
+
+ @Test
+ public void activeRecordLoadByQuery() {
+ DbContext ctx = new DbContext(dataSource);
+ UserAR user = new UserAR();
+ user.useContext(ctx); // Use ctx as DbContext
+ user.setName("Sam");
+ user.setAddress("Canada");
+ user.insert();
+ UserAR user2 = new UserAR().useContext(ctx).loadById(user.getName());
+ Assert.assertEquals("Canada", user2.getAddress());
+ }
+
+ @Test
+ public void dataMapperCrudTest() {
+ DbContext ctx = new DbContext(dataSource);
+ // ctx.setAllowShowSQL(true);
+ UserAR user = new UserAR();
+ for (int i = 1; i <= 10; i++) {
+ user.setName("Tom" + i);
+ user.setAddress("China" + i);
+ ctx.entityInsert(user);
+ }
+ user = new UserAR();
+ user.setName("Tom8");
+ ctx.entityLoad(user);
+ Assert.assertEquals("China8", user.getAddress());
+
+ user = ctx.entityLoadById(UserAR.class, "Tom7");
+ Assert.assertEquals("China7", user.getAddress());
+
+ user.setAddress("Canada");
+ ctx.entityUpdateTry(user);
+ Assert.assertEquals("Canada", ctx.entityLoadById(UserAR.class, "Tom7").getAddress());
+
+ ctx.entityDeleteTry(user);
+ ctx.entityDeleteTry(user, " or name=?", par("Tom2"));
+
+ Assert.assertEquals(7, ctx.entityFind(UserAR.class, " where name>?", par("Tom1")).size());
+ }
+
+ @Test
+ public void conditionsQuery() {
+ DbContext ctx = new DbContext(dataSource);
+ ctx.setAllowShowSQL(true);
+ final String name = "Tom";
+ final String age = null;
+ final String address = "China";
+ ctx.exe("insert into users (", //
+ notNull(" name", name), //
+ notNull(" ,age ", age), //
+ " ,address ", par(address), //
+ ") ", valuesQuestions());
+ ctx.exe("update users set ", //
+ notNull(" name", "=", "?, ", name), //
+ notNull(" age=?,", age), //
+ " address=? ", par(address), //
+ " where name is not null"//
+ );
+ Assert.assertEquals(1L, ctx.qryLongValue(//
+ "select count(*) from users where 1=1 ", //
+ notNull(" and name=? ", name), //
+ "Tom".equals(name) ? ctx.prepare(" and name=? ", par(name)) : "", //
+ "China".equals(address) ? new Object[]{" and address= ", que(address)} : "",//
+ " order by name"
+ ));
+ ctx.jdbcExecute("delete from users");
+ }
+
+ @Test
+ public void conditionsQuery2() { //use "when" method to test
+ DbContext ctx = new DbContext(dataSource);
+ ctx.setAllowShowSQL(true);
+ final String name = "Tom";
+ final String age = null;
+ final String address = "China";
+ ctx.exe("insert into users (", //
+ " name", par(name), //
+ when(age != null, " ,age ", par(age)), //
+ " ,address ", par(address), //
+ ") ", valuesQuestions());
+ ctx.exe("update users set ", //
+ " name=", que(name), //
+ when(age != null, ", age=", que(age)), //
+ when(address != null, ", address=", que(address)), //
+ " where name is not null"
+ );
+ Assert.assertEquals(1L, ctx.qryLongValue(//
+ "select count(*) from users where 1=1 ", //
+ when(name != null, " and name=", que(name)),//
+ when("Tom".equals(name), " and name=", que(name)),//
+ when("China".equals(address), " and address=", que(address)),//
+ " order by name"
+ ));
+ ctx.jdbcExecute("delete from users");
+ }
+
+ @Test
+ public void timeoutQuery() {
+ DbContext ctx = new DbContext(dataSource);
+ ctx.setAllowShowSQL(true);
+ final String name = "Tom";
+ final String age = null;
+ final String address = "China";
+ ctx.exe("insert into users (", //
+ " name", par(name), //
+ when(age != null, " ,age ", par(age)), //
+ " ,address ", par(address), //
+ ") ", valuesQuestions());
+ try {
+ List> r1 = ctx.qryMapList("select * from users", timeout(1));
+ Map r2 = ctx.qryMap("select * from users", timeout(1));
+ String r3 = ctx.qryString("select name from users where name=?", par(name), timeout(1));
+ System.out.println();
+ } catch (Exception e) {
+ if (e instanceof SQLException) {
+ //test on PGSQL
+ if (e.getMessage().indexOf("cancelled") != -1 || e.getMessage().indexOf("timeout") != -1) {
+ System.out.println("execute sql timeout...");
+ }
+ }
+
+ }
+ }
}