This commit is contained in:
Looly
2022-04-30 22:53:06 +08:00
parent a7ede583ec
commit 40aa543edd
36 changed files with 740 additions and 1189 deletions

View File

@@ -6,6 +6,7 @@ import cn.hutool.db.dialect.Dialect;
import cn.hutool.db.handler.BeanListHandler;
import cn.hutool.db.handler.EntityHandler;
import cn.hutool.db.handler.EntityListHandler;
import cn.hutool.db.handler.ResultSetUtil;
import cn.hutool.db.handler.NumberHandler;
import cn.hutool.db.handler.RsHandler;
import cn.hutool.db.handler.StringHandler;
@@ -32,9 +33,9 @@ import java.util.Map;
* 通过给定的数据源执行给定SQL或者给定数据源和方言执行相应的CRUD操作<br>
* 提供抽象方法getConnection和closeConnection用于自定义数据库连接的打开和关闭
*
* @author Luxiaolei
* @author looly
*/
public abstract class AbstractDb implements Serializable {
public abstract class AbstractDb<R extends AbstractDb<R>> implements ConnectionHolder, Serializable {
private static final long serialVersionUID = 3858951941916349062L;
protected final DataSource ds;
@@ -46,7 +47,7 @@ public abstract class AbstractDb implements Serializable {
* 是否大小写不敏感(默认大小写不敏感)
*/
protected boolean caseInsensitive = GlobalDbConfig.caseInsensitive;
protected SqlConnRunner runner;
protected DialectRunner runner;
// ------------------------------------------------------- Constructor start
@@ -58,36 +59,20 @@ public abstract class AbstractDb implements Serializable {
*/
public AbstractDb(final DataSource ds, final Dialect dialect) {
this.ds = ds;
this.runner = new SqlConnRunner(dialect);
this.runner = new DialectRunner(dialect);
}
// ------------------------------------------------------- Constructor end
/**
* 获得链接。根据实现不同,可以自定义获取连接的方式
*
* @return {@link Connection}
* @throws SQLException 连接获取异常
*/
public abstract Connection getConnection() throws SQLException;
/**
* 关闭连接<br>
* 自定义关闭连接有利于自定义回收连接机制,或者不关闭
*
* @param conn 连接 {@link Connection}
*/
public abstract void closeConnection(Connection conn);
/**
* 查询
*
* @param sql 查询语句
* @param params 参数
* @return 结果对象
* @throws SQLException SQL执行异常
* @throws DbRuntimeException SQL执行异常
* @since 3.1.1
*/
public List<Entity> query(final String sql, final Map<String, Object> params) throws SQLException {
public List<Entity> query(final String sql, final Map<String, Object> params) throws DbRuntimeException {
return query(sql, new EntityListHandler(this.caseInsensitive), params);
}
@@ -97,10 +82,10 @@ public abstract class AbstractDb implements Serializable {
* @param sql 查询语句
* @param params 参数
* @return 结果对象
* @throws SQLException SQL执行异常
* @throws DbRuntimeException SQL执行异常
* @since 3.1.1
*/
public List<Entity> query(final String sql, final Object... params) throws SQLException {
public List<Entity> query(final String sql, final Object... params) throws DbRuntimeException {
return query(sql, new EntityListHandler(this.caseInsensitive), params);
}
@@ -112,10 +97,10 @@ public abstract class AbstractDb implements Serializable {
* @param beanClass 元素Bean类型
* @param params 参数
* @return 结果对象
* @throws SQLException SQL执行异常
* @throws DbRuntimeException SQL执行异常
* @since 3.2.2
*/
public <T> List<T> query(final String sql, final Class<T> beanClass, final Object... params) throws SQLException {
public <T> List<T> query(final String sql, final Class<T> beanClass, final Object... params) throws DbRuntimeException {
return query(sql, new BeanListHandler<>(beanClass), params);
}
@@ -125,9 +110,9 @@ public abstract class AbstractDb implements Serializable {
* @param sql 查询语句
* @param params 参数
* @return 结果对象
* @throws SQLException SQL执行异常
* @throws DbRuntimeException SQL执行异常
*/
public Entity queryOne(final String sql, final Object... params) throws SQLException {
public Entity queryOne(final String sql, final Object... params) throws DbRuntimeException {
return query(sql, new EntityHandler(this.caseInsensitive), params);
}
@@ -137,9 +122,9 @@ public abstract class AbstractDb implements Serializable {
* @param sql 查询语句
* @param params 参数
* @return 结果对象
* @throws SQLException SQL执行异常
* @throws DbRuntimeException SQL执行异常
*/
public Number queryNumber(final String sql, final Object... params) throws SQLException {
public Number queryNumber(final String sql, final Object... params) throws DbRuntimeException {
return query(sql, new NumberHandler(), params);
}
@@ -149,9 +134,9 @@ public abstract class AbstractDb implements Serializable {
* @param sql 查询语句
* @param params 参数
* @return 结果对象
* @throws SQLException SQL执行异常
* @throws DbRuntimeException SQL执行异常
*/
public String queryString(final String sql, final Object... params) throws SQLException {
public String queryString(final String sql, final Object... params) throws DbRuntimeException {
return query(sql, new StringHandler(), params);
}
@@ -163,9 +148,9 @@ public abstract class AbstractDb implements Serializable {
* @param rsh 结果集处理对象
* @param params 参数
* @return 结果对象
* @throws SQLException SQL执行异常
* @throws DbRuntimeException SQL执行异常
*/
public <T> T query(final String sql, final RsHandler<T> rsh, final Object... params) throws SQLException {
public <T> T query(final String sql, final RsHandler<T> rsh, final Object... params) throws DbRuntimeException {
Connection conn = null;
try {
conn = this.getConnection();
@@ -183,10 +168,10 @@ public abstract class AbstractDb implements Serializable {
* @param rsh 结果集处理对象
* @param paramMap 参数
* @return 结果对象
* @throws SQLException SQL执行异常
* @throws DbRuntimeException SQL执行异常
* @since 5.2.2
*/
public <T> T query(final String sql, final RsHandler<T> rsh, final Map<String, Object> paramMap) throws SQLException {
public <T> T query(final String sql, final RsHandler<T> rsh, final Map<String, Object> paramMap) throws DbRuntimeException {
Connection conn = null;
try {
conn = this.getConnection();
@@ -204,10 +189,10 @@ public abstract class AbstractDb implements Serializable {
* @param statementFunc 自定义{@link PreparedStatement}创建函数
* @param rsh 结果集处理对象
* @return 结果对象
* @throws SQLException SQL执行异常
* @throws DbRuntimeException SQL执行异常
* @since 5.7.17
*/
public <T> T query(final Func1<Connection, PreparedStatement> statementFunc, final RsHandler<T> rsh) throws SQLException {
public <T> T query(final Func1<Connection, PreparedStatement> statementFunc, final RsHandler<T> rsh) throws DbRuntimeException {
Connection conn = null;
try {
conn = this.getConnection();
@@ -224,9 +209,9 @@ public abstract class AbstractDb implements Serializable {
* @param sql SQL
* @param params 参数
* @return 影响行数
* @throws SQLException SQL执行异常
* @throws DbRuntimeException SQL执行异常
*/
public int execute(final String sql, final Object... params) throws SQLException {
public int execute(final String sql, final Object... params) throws DbRuntimeException {
Connection conn = null;
try {
conn = this.getConnection();
@@ -243,9 +228,9 @@ public abstract class AbstractDb implements Serializable {
* @param sql SQL
* @param params 参数
* @return 主键
* @throws SQLException SQL执行异常
* @throws DbRuntimeException SQL执行异常
*/
public Long executeForGeneratedKey(final String sql, final Object... params) throws SQLException {
public Long executeForGeneratedKey(final String sql, final Object... params) throws DbRuntimeException {
Connection conn = null;
try {
conn = this.getConnection();
@@ -261,10 +246,10 @@ public abstract class AbstractDb implements Serializable {
* @param sql SQL
* @param paramsBatch 批量的参数
* @return 每个SQL执行影响的行数
* @throws SQLException SQL执行异常
* @throws DbRuntimeException SQL执行异常
* @since 5.4.2
*/
public int[] executeBatch(final String sql, final Iterable<Object[]> paramsBatch) throws SQLException {
public int[] executeBatch(final String sql, final Iterable<Object[]> paramsBatch) throws DbRuntimeException {
Connection conn = null;
try {
conn = this.getConnection();
@@ -279,10 +264,10 @@ public abstract class AbstractDb implements Serializable {
*
* @param sqls SQL列表
* @return 每个SQL执行影响的行数
* @throws SQLException SQL执行异常
* @throws DbRuntimeException SQL执行异常
* @since 4.5.6
*/
public int[] executeBatch(final String... sqls) throws SQLException {
public int[] executeBatch(final String... sqls) throws DbRuntimeException {
Connection conn = null;
try {
conn = this.getConnection();
@@ -297,10 +282,10 @@ public abstract class AbstractDb implements Serializable {
*
* @param sqls SQL列表
* @return 每个SQL执行影响的行数
* @throws SQLException SQL执行异常
* @throws DbRuntimeException SQL执行异常
* @since 5.4.2
*/
public int[] executeBatch(final Iterable<String> sqls) throws SQLException {
public int[] executeBatch(final Iterable<String> sqls) throws DbRuntimeException {
Connection conn = null;
try {
conn = this.getConnection();
@@ -317,13 +302,13 @@ public abstract class AbstractDb implements Serializable {
*
* @param record 记录
* @return 插入行数
* @throws SQLException SQL执行异常
* @throws DbRuntimeException SQL执行异常
*/
public int insert(final Entity record) throws SQLException {
public int insert(final Entity record) throws DbRuntimeException {
Connection conn = null;
try {
conn = this.getConnection();
return runner.insert(conn, record);
return runner.insert(conn, record)[0];
} finally {
this.closeConnection(conn);
}
@@ -336,10 +321,10 @@ public abstract class AbstractDb implements Serializable {
* @param record 记录
* @param keys 需要检查唯一性的字段
* @return 插入行数
* @throws SQLException SQL执行异常
* @throws DbRuntimeException SQL执行异常
* @since 4.0.10
*/
public int insertOrUpdate(final Entity record, final String... keys) throws SQLException {
public int insertOrUpdate(final Entity record, final String... keys) throws DbRuntimeException {
Connection conn = null;
try {
conn = this.getConnection();
@@ -353,13 +338,14 @@ public abstract class AbstractDb implements Serializable {
* 使用upsert语义插入或更新数据<br>
* 根据给定的字段名查询数据,如果存在则更新这些数据,否则执行插入
* 如果方言未实现本方法内部会自动调用insertOrUpdate来实现功能由于upsert和insert使用有区别为了兼容性保留原有insertOrUpdate不做变动
*
* @param record 记录
* @param keys 需要检查唯一性的字段
* @return 插入行数
* @throws SQLException SQL执行异常
* @throws DbRuntimeException SQL执行异常
* @since 5.7.21
*/
public int upsert(final Entity record, final String... keys) throws SQLException {
public int upsert(final Entity record, final String... keys) throws DbRuntimeException {
Connection conn = null;
try {
conn = this.getConnection();
@@ -376,13 +362,13 @@ public abstract class AbstractDb implements Serializable {
*
* @param records 记录列表
* @return 插入行数
* @throws SQLException SQL执行异常
* @throws DbRuntimeException SQL执行异常
*/
public int[] insert(final Collection<Entity> records) throws SQLException {
public int[] insert(final Collection<Entity> records) throws DbRuntimeException {
Connection conn = null;
try {
conn = this.getConnection();
return runner.insert(conn, records);
return runner.insert(conn, records.toArray(new Entity[0]));
} finally {
this.closeConnection(conn);
}
@@ -393,13 +379,13 @@ public abstract class AbstractDb implements Serializable {
*
* @param record 记录
* @return 主键列表
* @throws SQLException SQL执行异常
* @throws DbRuntimeException SQL执行异常
*/
public List<Object> insertForGeneratedKeys(final Entity record) throws SQLException {
public List<Object> insertForGeneratedKeys(final Entity record) throws DbRuntimeException {
Connection conn = null;
try {
conn = this.getConnection();
return runner.insertForGeneratedKeys(conn, record);
return runner.insert(conn, record, ResultSetUtil::handleRowToList);
} finally {
this.closeConnection(conn);
}
@@ -410,13 +396,13 @@ public abstract class AbstractDb implements Serializable {
*
* @param record 记录
* @return 主键
* @throws SQLException SQL执行异常
* @throws DbRuntimeException SQL执行异常
*/
public Long insertForGeneratedKey(final Entity record) throws SQLException {
public Long insertForGeneratedKey(final Entity record) throws DbRuntimeException {
Connection conn = null;
try {
conn = this.getConnection();
return runner.insertForGeneratedKey(conn, record);
return runner.insert(conn, record, ResultSetUtil::toLong);
} finally {
this.closeConnection(conn);
}
@@ -429,9 +415,9 @@ public abstract class AbstractDb implements Serializable {
* @param field 字段名,最好是主键
* @param value 值值可以是列表或数组被当作IN查询处理
* @return 删除行数
* @throws SQLException SQL执行异常
* @throws DbRuntimeException SQL执行异常
*/
public int del(final String tableName, final String field, final Object value) throws SQLException {
public int del(final String tableName, final String field, final Object value) throws DbRuntimeException {
return del(Entity.create(tableName).set(field, value));
}
@@ -440,9 +426,9 @@ public abstract class AbstractDb implements Serializable {
*
* @param where 条件
* @return 影响行数
* @throws SQLException SQL执行异常
* @throws DbRuntimeException SQL执行异常
*/
public int del(final Entity where) throws SQLException {
public int del(final Entity where) throws DbRuntimeException {
Connection conn = null;
try {
conn = this.getConnection();
@@ -459,9 +445,9 @@ public abstract class AbstractDb implements Serializable {
* @param record 记录
* @param where 条件
* @return 影响行数
* @throws SQLException SQL执行异常
* @throws DbRuntimeException SQL执行异常
*/
public int update(final Entity record, final Entity where) throws SQLException {
public int update(final Entity record, final Entity where) throws DbRuntimeException {
Connection conn = null;
try {
conn = this.getConnection();
@@ -482,9 +468,9 @@ public abstract class AbstractDb implements Serializable {
* @param field 字段名
* @param value 字段值
* @return 记录
* @throws SQLException SQL执行异常
* @throws DbRuntimeException SQL执行异常
*/
public <T> Entity get(final String tableName, final String field, final T value) throws SQLException {
public <T> Entity get(final String tableName, final String field, final T value) throws DbRuntimeException {
return this.get(Entity.create(tableName).set(field, value));
}
@@ -493,9 +479,9 @@ public abstract class AbstractDb implements Serializable {
*
* @param where 条件
* @return 记录
* @throws SQLException SQL执行异常
* @throws DbRuntimeException SQL执行异常
*/
public Entity get(final Entity where) throws SQLException {
public Entity get(final Entity where) throws DbRuntimeException {
return find(where.getFieldNames(), where, new EntityHandler(this.caseInsensitive));
}
@@ -510,13 +496,13 @@ public abstract class AbstractDb implements Serializable {
* @param where 条件实体类(包含表名)
* @param rsh 结果集处理对象
* @return 结果对象
* @throws SQLException SQL执行异常
* @throws DbRuntimeException SQL执行异常
*/
public <T> T find(final Collection<String> fields, final Entity where, final RsHandler<T> rsh) throws SQLException {
public <T> T find(final Collection<String> fields, final Entity where, final RsHandler<T> rsh) throws DbRuntimeException {
Connection conn = null;
try {
conn = this.getConnection();
return runner.find(conn, fields, where, rsh);
return runner.find(conn, Query.of(where).setFields(fields), rsh);
} finally {
this.closeConnection(conn);
}
@@ -529,10 +515,10 @@ public abstract class AbstractDb implements Serializable {
* @param fields 返回的字段列表null则返回所有字段
* @param where 条件实体类(包含表名)
* @return 结果Entity列表
* @throws SQLException SQL执行异常
* @throws DbRuntimeException SQL执行异常
* @since 4.5.16
*/
public List<Entity> find(final Collection<String> fields, final Entity where) throws SQLException {
public List<Entity> find(final Collection<String> fields, final Entity where) throws DbRuntimeException {
return find(fields, where, new EntityListHandler(this.caseInsensitive));
}
@@ -544,10 +530,10 @@ public abstract class AbstractDb implements Serializable {
* @param query {@link Query}对象,此对象中可以定义返回字段、查询条件,查询的表、分页等信息
* @param rsh 结果集处理对象
* @return 结果对象
* @throws SQLException SQL执行异常
* @throws DbRuntimeException SQL执行异常
* @since 4.0.0
*/
public <T> T find(final Query query, final RsHandler<T> rsh) throws SQLException {
public <T> T find(final Query query, final RsHandler<T> rsh) throws DbRuntimeException {
Connection conn = null;
try {
conn = this.getConnection();
@@ -566,9 +552,9 @@ public abstract class AbstractDb implements Serializable {
* @param rsh 结果集处理对象
* @param fields 字段列表,可变长参数如果无值表示查询全部字段
* @return 结果对象
* @throws SQLException SQL执行异常
* @throws DbRuntimeException SQL执行异常
*/
public <T> T find(final Entity where, final RsHandler<T> rsh, final String... fields) throws SQLException {
public <T> T find(final Entity where, final RsHandler<T> rsh, final String... fields) throws DbRuntimeException {
return find(CollUtil.newArrayList(fields), where, rsh);
}
@@ -578,10 +564,10 @@ public abstract class AbstractDb implements Serializable {
*
* @param where 条件实体类(包含表名)
* @return 数据对象列表
* @throws SQLException SQL执行异常
* @throws DbRuntimeException SQL执行异常
* @since 3.2.1
*/
public List<Entity> find(final Entity where) throws SQLException {
public List<Entity> find(final Entity where) throws DbRuntimeException {
return find(where.getFieldNames(), where, new EntityListHandler(this.caseInsensitive));
}
@@ -593,10 +579,10 @@ public abstract class AbstractDb implements Serializable {
* @param where 条件实体类(包含表名)
* @param beanClass Bean类
* @return 数据对象列表
* @throws SQLException SQL执行异常
* @throws DbRuntimeException SQL执行异常
* @since 3.2.2
*/
public <T> List<T> find(final Entity where, final Class<T> beanClass) throws SQLException {
public <T> List<T> find(final Entity where, final Class<T> beanClass) throws DbRuntimeException {
return find(where.getFieldNames(), where, BeanListHandler.create(beanClass));
}
@@ -606,9 +592,9 @@ public abstract class AbstractDb implements Serializable {
*
* @param where 条件实体类(包含表名)
* @return 数据对象列表
* @throws SQLException SQL执行异常
* @throws DbRuntimeException SQL执行异常
*/
public List<Entity> findAll(final Entity where) throws SQLException {
public List<Entity> findAll(final Entity where) throws DbRuntimeException {
return find(where, EntityListHandler.create());
}
@@ -620,10 +606,10 @@ public abstract class AbstractDb implements Serializable {
* @param where 条件实体类(包含表名)
* @param beanClass 返回的对象类型
* @return 数据对象列表
* @throws SQLException SQL执行异常
* @throws DbRuntimeException SQL执行异常
* @since 3.2.2
*/
public <T> List<T> findAll(final Entity where, final Class<T> beanClass) throws SQLException {
public <T> List<T> findAll(final Entity where, final Class<T> beanClass) throws DbRuntimeException {
return find(where, BeanListHandler.create(beanClass));
}
@@ -632,9 +618,9 @@ public abstract class AbstractDb implements Serializable {
*
* @param tableName 表名
* @return 数据对象列表
* @throws SQLException SQL执行异常
* @throws DbRuntimeException SQL执行异常
*/
public List<Entity> findAll(final String tableName) throws SQLException {
public List<Entity> findAll(final String tableName) throws DbRuntimeException {
return findAll(Entity.create(tableName));
}
@@ -645,9 +631,9 @@ public abstract class AbstractDb implements Serializable {
* @param field 字段名
* @param value 字段值
* @return 数据对象列表
* @throws SQLException SQL执行异常
* @throws DbRuntimeException SQL执行异常
*/
public List<Entity> findBy(final String tableName, final String field, final Object value) throws SQLException {
public List<Entity> findBy(final String tableName, final String field, final Object value) throws DbRuntimeException {
return findAll(Entity.create(tableName).set(field, value));
}
@@ -657,10 +643,10 @@ public abstract class AbstractDb implements Serializable {
* @param tableName 表名
* @param wheres 条件,多个条件的连接逻辑使用{@link Condition#setLinkOperator(LogicalOperator)} 定义
* @return 数据对象列表
* @throws SQLException SQL执行异常
* @throws DbRuntimeException SQL执行异常
* @since 4.0.0
*/
public List<Entity> findBy(final String tableName, final Condition... wheres) throws SQLException {
public List<Entity> findBy(final String tableName, final Condition... wheres) throws DbRuntimeException {
final Query query = new Query(wheres, tableName);
return find(query, new EntityListHandler(this.caseInsensitive));
}
@@ -673,9 +659,9 @@ public abstract class AbstractDb implements Serializable {
* @param value 字段值
* @param likeType {@link LikeType}
* @return 数据对象列表
* @throws SQLException SQL执行异常
* @throws DbRuntimeException SQL执行异常
*/
public List<Entity> findLike(final String tableName, final String field, final String value, final LikeType likeType) throws SQLException {
public List<Entity> findLike(final String tableName, final String field, final String value, final LikeType likeType) throws DbRuntimeException {
return findAll(Entity.create(tableName).set(field, SqlUtil.buildLikeValue(value, likeType, true)));
}
@@ -684,13 +670,13 @@ public abstract class AbstractDb implements Serializable {
*
* @param where 查询条件
* @return 复合条件的结果数
* @throws SQLException SQL执行异常
* @throws DbRuntimeException SQL执行异常
*/
public long count(final Entity where) throws SQLException {
public long count(final Entity where) throws DbRuntimeException {
Connection conn = null;
try {
conn = this.getConnection();
return runner.count(conn, where);
return runner.count(conn, Query.of(where));
} finally {
this.closeConnection(conn);
}
@@ -701,9 +687,9 @@ public abstract class AbstractDb implements Serializable {
*
* @param sql sql构造器
* @return 复合条件的结果数
* @throws SQLException SQL执行异常
* @throws DbRuntimeException SQL执行异常
*/
public long count(final SqlBuilder sql) throws SQLException {
public long count(final SqlBuilder sql) throws DbRuntimeException {
Connection conn = null;
try {
conn = this.getConnection();
@@ -719,74 +705,19 @@ public abstract class AbstractDb implements Serializable {
* @param selectSql 查询SQL语句
* @param params 查询参数
* @return 复合条件的结果数
* @throws SQLException SQL执行异常
* @throws DbRuntimeException SQL执行异常
* @since 5.6.6
*/
public long count(final CharSequence selectSql, final Object... params) throws SQLException {
public long count(final CharSequence selectSql, final Object... params) throws DbRuntimeException {
Connection conn = null;
try {
conn = this.getConnection();
return runner.count(conn, selectSql, params);
return runner.count(conn, SqlBuilder.of(selectSql).addParams(params));
} finally {
this.closeConnection(conn);
}
}
/**
* 分页查询<br>
* 查询条件为多个key value对表示默认key = value如果使用其它条件可以使用where.put("key", " &gt; 1")value也可以传Condition对象key被忽略
*
* @param <T> 结果对象类型
* @param fields 返回的字段列表null则返回所有字段
* @param where 条件实体类(包含表名)
* @param page 页码0表示第一页
* @param numPerPage 每页条目数
* @param rsh 结果集处理对象
* @return 结果对象
* @throws SQLException SQL执行异常
*/
public <T> T page(final Collection<String> fields, final Entity where, final int page, final int numPerPage, final RsHandler<T> rsh) throws SQLException {
Connection conn = null;
try {
conn = this.getConnection();
return runner.page(conn, fields, where, page, numPerPage, rsh);
} finally {
this.closeConnection(conn);
}
}
/**
* 分页查询<br>
* 查询条件为多个key value对表示默认key = value如果使用其它条件可以使用where.put("key", " &gt; 1")value也可以传Condition对象key被忽略
*
* @param <T> 结果对象类型
* @param where 条件实体类(包含表名)
* @param page 页码0表示第一页
* @param numPerPage 每页条目数
* @param rsh 结果集处理对象
* @return 结果对象
* @throws SQLException SQL执行异常
* @since 3.2.2
*/
public <T> T page(final Entity where, final int page, final int numPerPage, final RsHandler<T> rsh) throws SQLException {
return page(where, new Page(page, numPerPage), rsh);
}
/**
* 分页查询结果为Entity列表不计算总数<br>
* 查询条件为多个key value对表示默认key = value如果使用其它条件可以使用where.put("key", " &gt; 1")value也可以传Condition对象key被忽略
*
* @param where 条件实体类(包含表名)
* @param page 页码0表示第一页
* @param numPerPage 每页条目数
* @return 结果对象
* @throws SQLException SQL执行异常
* @since 3.2.2
*/
public List<Entity> pageForEntityList(final Entity where, final int page, final int numPerPage) throws SQLException {
return pageForEntityList(where, new Page(page, numPerPage));
}
/**
* 分页查询结果为Entity列表不计算总数<br>
* 查询条件为多个key value对表示默认key = value如果使用其它条件可以使用where.put("key", " &gt; 1")value也可以传Condition对象key被忽略
@@ -794,10 +725,10 @@ public abstract class AbstractDb implements Serializable {
* @param where 条件实体类(包含表名)
* @param page 分页对象
* @return 结果对象
* @throws SQLException SQL执行异常
* @throws DbRuntimeException SQL执行异常
* @since 3.2.2
*/
public List<Entity> pageForEntityList(final Entity where, final Page page) throws SQLException {
public List<Entity> pageForEntityList(final Entity where, final Page page) throws DbRuntimeException {
return page(where, page, new EntityListHandler(this.caseInsensitive));
}
@@ -810,10 +741,10 @@ public abstract class AbstractDb implements Serializable {
* @param page 分页对象
* @param rsh 结果集处理对象
* @return 结果对象
* @throws SQLException SQL执行异常
* @throws DbRuntimeException SQL执行异常
* @since 3.2.2
*/
public <T> T page(final Entity where, final Page page, final RsHandler<T> rsh) throws SQLException {
public <T> T page(final Entity where, final Page page, final RsHandler<T> rsh) throws DbRuntimeException {
return page(where.getFieldNames(), where, page, rsh);
}
@@ -827,13 +758,13 @@ public abstract class AbstractDb implements Serializable {
* @param page 分页对象
* @param rsh 结果集处理对象
* @return 结果对象
* @throws SQLException SQL执行异常
* @throws DbRuntimeException SQL执行异常
*/
public <T> T page(final Collection<String> fields, final Entity where, final Page page, final RsHandler<T> rsh) throws SQLException {
public <T> T page(final Collection<String> fields, final Entity where, final Page page, final RsHandler<T> rsh) throws DbRuntimeException {
Connection conn = null;
try {
conn = this.getConnection();
return runner.page(conn, fields, where, page, rsh);
return runner.page(conn, Query.of(where).setFields(fields).setPage(page), rsh);
} finally {
this.closeConnection(conn);
}
@@ -848,10 +779,10 @@ public abstract class AbstractDb implements Serializable {
* @param rsh 结果集处理对象
* @param params 参数
* @return 结果对象
* @throws SQLException SQL执行异常
* @throws DbRuntimeException SQL执行异常
* @since 5.6.6
*/
public <T> T page(final CharSequence sql, final Page page, final RsHandler<T> rsh, final Object... params) throws SQLException {
public <T> T page(final CharSequence sql, final Page page, final RsHandler<T> rsh, final Object... params) throws DbRuntimeException {
Connection conn = null;
try {
conn = this.getConnection();
@@ -869,9 +800,9 @@ public abstract class AbstractDb implements Serializable {
* @param page 分页对象
* @param rsh 结果集处理对象
* @return 结果对象
* @throws SQLException SQL执行异常
* @throws DbRuntimeException SQL执行异常
*/
public <T> T page(final SqlBuilder sql, final Page page, final RsHandler<T> rsh) throws SQLException {
public <T> T page(final SqlBuilder sql, final Page page, final RsHandler<T> rsh) throws DbRuntimeException {
Connection conn = null;
try {
conn = this.getConnection();
@@ -888,10 +819,10 @@ public abstract class AbstractDb implements Serializable {
* @param page 分页对象
* @param params 参数列表
* @return 结果对象
* @throws SQLException SQL执行异常
* @throws DbRuntimeException SQL执行异常
* @since 5.5.3
*/
public PageResult<Entity> page(final CharSequence sql, final Page page, final Object... params) throws SQLException {
public PageResult<Entity> page(final CharSequence sql, final Page page, final Object... params) throws DbRuntimeException {
Connection conn = null;
try {
conn = this.getConnection();
@@ -910,9 +841,9 @@ public abstract class AbstractDb implements Serializable {
* @param pageNumber 页码
* @param pageSize 每页结果数
* @return 结果对象
* @throws SQLException SQL执行异常
* @throws DbRuntimeException SQL执行异常
*/
public PageResult<Entity> page(final Collection<String> fields, final Entity where, final int pageNumber, final int pageSize) throws SQLException {
public PageResult<Entity> page(final Collection<String> fields, final Entity where, final int pageNumber, final int pageSize) throws DbRuntimeException {
return page(fields, where, new Page(pageNumber, pageSize));
}
@@ -924,13 +855,13 @@ public abstract class AbstractDb implements Serializable {
* @param where 条件实体类(包含表名)
* @param page 分页对象
* @return 结果对象
* @throws SQLException SQL执行异常
* @throws DbRuntimeException SQL执行异常
*/
public PageResult<Entity> page(final Collection<String> fields, final Entity where, final Page page) throws SQLException {
public PageResult<Entity> page(final Collection<String> fields, final Entity where, final Page page) throws DbRuntimeException {
Connection conn = null;
try {
conn = this.getConnection();
return runner.page(conn, fields, where, page);
return runner.page(conn, Query.of(where).setFields(fields).setPage(page));
} finally {
this.closeConnection(conn);
}
@@ -944,10 +875,10 @@ public abstract class AbstractDb implements Serializable {
* @param page 页码
* @param numPerPage 每页条目数
* @return 分页结果集
* @throws SQLException SQL执行异常
* @throws DbRuntimeException SQL执行异常
* @since 3.2.2
*/
public PageResult<Entity> page(final Entity where, final int page, final int numPerPage) throws SQLException {
public PageResult<Entity> page(final Entity where, final int page, final int numPerPage) throws DbRuntimeException {
return this.page(where, new Page(page, numPerPage));
}
@@ -958,9 +889,9 @@ public abstract class AbstractDb implements Serializable {
* @param where 条件实体类(包含表名)
* @param page 分页对象
* @return 分页结果集
* @throws SQLException SQL执行异常
* @throws DbRuntimeException SQL执行异常
*/
public PageResult<Entity> page(final Entity where, final Page page) throws SQLException {
public PageResult<Entity> page(final Entity where, final Page page) throws DbRuntimeException {
return this.page(where.getFieldNames(), where, page);
}
// ---------------------------------------------------------------------------- CRUD end
@@ -974,26 +905,30 @@ public abstract class AbstractDb implements Serializable {
* @param caseInsensitive 否在结果中忽略大小写
* @since 5.2.4
*/
public void setCaseInsensitive(final boolean caseInsensitive) {
@SuppressWarnings("unchecked")
public R setCaseInsensitive(final boolean caseInsensitive) {
this.caseInsensitive = caseInsensitive;
return (R) this;
}
/**
* 获取{@link SqlConnRunner}
* 获取{@link DialectRunner}
*
* @return {@link SqlConnRunner}
* @return {@link DialectRunner}
*/
public SqlConnRunner getRunner() {
public DialectRunner getRunner() {
return runner;
}
/**
* 设置 {@link SqlConnRunner}
* 设置 {@link DialectRunner}
*
* @param runner {@link SqlConnRunner}
* @param runner {@link DialectRunner}
*/
public void setRunner(final SqlConnRunner runner) {
@SuppressWarnings("unchecked")
public R setRunner(final DialectRunner runner) {
this.runner = runner;
return (R) this;
}
/**
@@ -1003,7 +938,7 @@ public abstract class AbstractDb implements Serializable {
* @return this
* @since 4.0.0
*/
public AbstractDb setWrapper(final Character wrapperChar) {
public R setWrapper(final Character wrapperChar) {
return setWrapper(new Wrapper(wrapperChar));
}
@@ -1014,9 +949,10 @@ public abstract class AbstractDb implements Serializable {
* @return this
* @since 4.0.0
*/
public AbstractDb setWrapper(final Wrapper wrapper) {
@SuppressWarnings("unchecked")
public R setWrapper(final Wrapper wrapper) {
this.runner.setWrapper(wrapper);
return this;
return (R) this;
}
/**
@@ -1026,7 +962,7 @@ public abstract class AbstractDb implements Serializable {
* @return this
* @since 4.5.7
*/
public AbstractDb disableWrapper() {
public R disableWrapper() {
return setWrapper((Wrapper) null);
}
// ---------------------------------------------------------------------------- Getters and Setters end
@@ -1037,12 +973,16 @@ public abstract class AbstractDb implements Serializable {
* 检查数据库是否支持事务此项检查同一个数据源只检查一次如果不支持抛出DbRuntimeException异常
*
* @param conn Connection
* @throws SQLException 获取元数据信息失败
* @throws DbRuntimeException 获取元数据信息失败
* @throws DbRuntimeException 不支持事务
*/
protected void checkTransactionSupported(final Connection conn) throws SQLException, DbRuntimeException {
protected void checkTransactionSupported(final Connection conn) throws DbRuntimeException {
if (null == isSupportTransaction) {
isSupportTransaction = conn.getMetaData().supportsTransactions();
try {
isSupportTransaction = conn.getMetaData().supportsTransactions();
} catch (final SQLException e) {
throw new DbRuntimeException(e);
}
}
if (false == isSupportTransaction) {
throw new DbRuntimeException("Transaction not supported for current database!");

View File

@@ -1,11 +1,10 @@
package cn.hutool.db;
import java.sql.SQLException;
import java.util.Collection;
import cn.hutool.core.lang.func.Func0;
import cn.hutool.core.map.MapUtil;
import java.util.Collection;
/**
* 动态实体类<br>
* 提供了针对自身实体的增删改方法
@@ -79,7 +78,7 @@ public class ActiveEntity extends Entity {
* 构造
*/
public ActiveEntity() {
this(Db.use(), (String) null);
this(Db.of(), (String) null);
}
/**
@@ -88,7 +87,7 @@ public class ActiveEntity extends Entity {
* @param tableName 表名
*/
public ActiveEntity(final String tableName) {
this(Db.use(), tableName);
this(Db.of(), tableName);
}
/**
@@ -97,7 +96,7 @@ public class ActiveEntity extends Entity {
* @param entity 非动态实体
*/
public ActiveEntity(final Entity entity) {
this(Db.use(), entity);
this(Db.of(), entity);
}
/**
@@ -186,11 +185,7 @@ public class ActiveEntity extends Entity {
* @return this
*/
public ActiveEntity add() {
try {
db.insert(this);
} catch (final SQLException e) {
throw new DbRuntimeException(e);
}
db.insert(this);
return this;
}
@@ -200,13 +195,9 @@ public class ActiveEntity extends Entity {
* @return this
*/
public ActiveEntity load() {
try {
final Entity result = db.get(this);
if(MapUtil.isNotEmpty(result)) {
this.putAll(result);
}
} catch (final SQLException e) {
throw new DbRuntimeException(e);
final Entity result = db.get(this);
if(MapUtil.isNotEmpty(result)) {
this.putAll(result);
}
return this;
}
@@ -217,11 +208,7 @@ public class ActiveEntity extends Entity {
* @return this
*/
public ActiveEntity del() {
try {
db.del(this);
} catch (final SQLException e) {
throw new DbRuntimeException(e);
}
db.del(this);
return this;
}
@@ -232,11 +219,7 @@ public class ActiveEntity extends Entity {
* @return this
*/
public ActiveEntity update(final String primaryKey) {
try {
db.update(this, Entity.create().set(primaryKey, this.get(primaryKey)));
} catch (final SQLException e) {
throw new DbRuntimeException(e);
}
db.update(this, Entity.create().set(primaryKey, this.get(primaryKey)));
return this;
}
// -------------------------------------------------------------------------- CRUD end

View File

@@ -0,0 +1,27 @@
package cn.hutool.db;
import java.sql.Connection;
/**
* 控制{@link Connection}获取和关闭
*
* @author looly
* @since 6.0.0
*/
public interface ConnectionHolder {
/**
* 获得链接。根据实现不同,可以自定义获取连接的方式
*
* @return {@link Connection}
* @throws DbRuntimeException 连接获取异常
*/
Connection getConnection() throws DbRuntimeException;
/**
* 关闭连接<br>
* 自定义关闭连接有利于自定义回收连接机制,或者不关闭
*
* @param conn 连接 {@link Connection}
*/
void closeConnection(Connection conn);
}

View File

@@ -5,7 +5,6 @@ import cn.hutool.core.text.StrUtil;
import cn.hutool.db.ds.DSFactory;
import javax.sql.DataSource;
import java.sql.SQLException;
import java.util.Arrays;
import java.util.List;
@@ -71,7 +70,7 @@ public class DaoTemplate {
* @param ds 数据源
*/
public DaoTemplate(final String tableName, final String primaryKeyField, final DataSource ds) {
this(tableName, primaryKeyField, Db.use(ds));
this(tableName, primaryKeyField, Db.of(ds));
}
/**
@@ -97,9 +96,9 @@ public class DaoTemplate {
*
* @param entity 实体对象
* @return 插入行数
* @throws SQLException SQL执行异常
* @throws DbRuntimeException SQL执行异常
*/
public int add(final Entity entity) throws SQLException {
public int add(final Entity entity) throws DbRuntimeException {
return db.insert(fixEntity(entity));
}
@@ -108,9 +107,9 @@ public class DaoTemplate {
*
* @param entity 实体对象
* @return 主键列表
* @throws SQLException SQL执行异常
* @throws DbRuntimeException SQL执行异常
*/
public List<Object> addForGeneratedKeys(final Entity entity) throws SQLException {
public List<Object> addForGeneratedKeys(final Entity entity) throws DbRuntimeException {
return db.insertForGeneratedKeys(fixEntity(entity));
}
@@ -119,9 +118,9 @@ public class DaoTemplate {
*
* @param entity 实体对象
* @return 自增主键
* @throws SQLException SQL执行异常
* @throws DbRuntimeException SQL执行异常
*/
public Long addForGeneratedKey(final Entity entity) throws SQLException {
public Long addForGeneratedKey(final Entity entity) throws DbRuntimeException {
return db.insertForGeneratedKey(fixEntity(entity));
}
//------------------------------------------------------------- Add end
@@ -134,9 +133,9 @@ public class DaoTemplate {
* @param <T> 主键类型
* @param pk 主键
* @return 删除行数
* @throws SQLException SQL执行异常
* @throws DbRuntimeException SQL执行异常
*/
public <T> int del(final T pk) throws SQLException {
public <T> int del(final T pk) throws DbRuntimeException {
if (pk == null) {
return 0;
}
@@ -150,9 +149,9 @@ public class DaoTemplate {
* @param field 字段名
* @param value 字段值
* @return 删除行数
* @throws SQLException SQL执行异常
* @throws DbRuntimeException SQL执行异常
*/
public <T> int del(final String field, final T value) throws SQLException {
public <T> int del(final String field, final T value) throws DbRuntimeException {
if (StrUtil.isBlank(field)) {
return 0;
}
@@ -163,12 +162,11 @@ public class DaoTemplate {
/**
* 删除
*
* @param <T> 主键类型
* @param where 删除条件当条件为空时返回0防止误删全表
* @return 删除行数
* @throws SQLException SQL执行异常
* @throws DbRuntimeException SQL执行异常
*/
public <T> int del(final Entity where) throws SQLException {
public int del(final Entity where) throws DbRuntimeException {
if (MapUtil.isEmpty(where)) {
return 0;
}
@@ -184,9 +182,9 @@ public class DaoTemplate {
* @param record 更新的内容
* @param where 条件
* @return 更新条目数
* @throws SQLException SQL执行异常
* @throws DbRuntimeException SQL执行异常
*/
public int update(final Entity record, final Entity where) throws SQLException {
public int update(final Entity record, final Entity where) throws DbRuntimeException {
if (MapUtil.isEmpty(record)) {
return 0;
}
@@ -198,16 +196,16 @@ public class DaoTemplate {
*
* @param entity 实体对象,必须包含主键
* @return 更新行数
* @throws SQLException SQL执行异常
* @throws DbRuntimeException SQL执行异常
*/
public int update(Entity entity) throws SQLException {
public int update(Entity entity) throws DbRuntimeException {
if (MapUtil.isEmpty(entity)) {
return 0;
}
entity = fixEntity(entity);
final Object pk = entity.get(primaryKeyField);
if (null == pk) {
throw new SQLException(StrUtil.format("Please determine `{}` for update", primaryKeyField));
throw new DbRuntimeException(StrUtil.format("Please determine `{}` for update", primaryKeyField));
}
final Entity where = Entity.create(tableName).set(primaryKeyField, pk);
@@ -222,9 +220,9 @@ public class DaoTemplate {
*
* @param entity 实体,当包含主键时更新,否则新增
* @return 新增或更新条数
* @throws SQLException SQL执行异常
* @throws DbRuntimeException SQL执行异常
*/
public int addOrUpdate(final Entity entity) throws SQLException {
public int addOrUpdate(final Entity entity) throws DbRuntimeException {
return null == entity.get(primaryKeyField) ? add(entity) : update(entity);
}
//------------------------------------------------------------- Update end
@@ -237,9 +235,9 @@ public class DaoTemplate {
* @param <T> 主键类型
* @param pk 主键值
* @return 记录
* @throws SQLException SQL执行异常
* @throws DbRuntimeException SQL执行异常
*/
public <T> Entity get(final T pk) throws SQLException {
public <T> Entity get(final T pk) throws DbRuntimeException {
return this.get(primaryKeyField, pk);
}
@@ -251,9 +249,9 @@ public class DaoTemplate {
* @param field 字段名
* @param value 字段值
* @return 记录
* @throws SQLException SQL执行异常
* @throws DbRuntimeException SQL执行异常
*/
public <T> Entity get(final String field, final T value) throws SQLException {
public <T> Entity get(final String field, final T value) throws DbRuntimeException {
return this.get(Entity.create(tableName).set(field, value));
}
@@ -262,9 +260,9 @@ public class DaoTemplate {
*
* @param where 条件
* @return 记录
* @throws SQLException SQL执行异常
* @throws DbRuntimeException SQL执行异常
*/
public Entity get(final Entity where) throws SQLException {
public Entity get(final Entity where) throws DbRuntimeException {
return db.get(fixEntity(where));
}
//------------------------------------------------------------- Get end
@@ -278,9 +276,9 @@ public class DaoTemplate {
* @param field 字段名
* @param value 字段值
* @return 记录
* @throws SQLException SQL执行异常
* @throws DbRuntimeException SQL执行异常
*/
public <T> List<Entity> find(final String field, final T value) throws SQLException {
public <T> List<Entity> find(final String field, final T value) throws DbRuntimeException {
return this.find(Entity.create(tableName).set(field, value));
}
@@ -288,9 +286,9 @@ public class DaoTemplate {
* 查询当前表的所有记录
*
* @return 记录
* @throws SQLException SQL执行异常
* @throws DbRuntimeException SQL执行异常
*/
public List<Entity> findAll() throws SQLException {
public List<Entity> findAll() throws DbRuntimeException {
return this.find(Entity.create(tableName));
}
@@ -299,9 +297,9 @@ public class DaoTemplate {
*
* @param where 查询条件
* @return 记录
* @throws SQLException SQL执行异常
* @throws DbRuntimeException SQL执行异常
*/
public List<Entity> find(final Entity where) throws SQLException {
public List<Entity> find(final Entity where) throws DbRuntimeException {
return db.find(null, fixEntity(where));
}
@@ -313,9 +311,9 @@ public class DaoTemplate {
* @param sql SQL语句
* @param params SQL占位符中对应的参数
* @return 记录
* @throws SQLException SQL执行异常
* @throws DbRuntimeException SQL执行异常
*/
public List<Entity> findBySql(String sql, final Object... params) throws SQLException {
public List<Entity> findBySql(String sql, final Object... params) throws DbRuntimeException {
final String selectKeyword = StrUtil.subPre(sql.trim(), 6).toLowerCase();
if (false == "select".equals(selectKeyword)) {
sql = "SELECT * FROM " + this.tableName + " " + sql;
@@ -330,9 +328,9 @@ public class DaoTemplate {
* @param page 分页对象
* @param selectFields 查询的字段列表
* @return 分页结果集
* @throws SQLException SQL执行异常
* @throws DbRuntimeException SQL执行异常
*/
public PageResult<Entity> page(final Entity where, final Page page, final String... selectFields) throws SQLException {
public PageResult<Entity> page(final Entity where, final Page page, final String... selectFields) throws DbRuntimeException {
return db.page(Arrays.asList(selectFields), fixEntity(where), page);
}
@@ -342,9 +340,9 @@ public class DaoTemplate {
* @param where 条件
* @param page 分页对象
* @return 分页结果集
* @throws SQLException SQL执行异常
* @throws DbRuntimeException SQL执行异常
*/
public PageResult<Entity> page(final Entity where, final Page page) throws SQLException {
public PageResult<Entity> page(final Entity where, final Page page) throws DbRuntimeException {
return db.page(fixEntity(where), page);
}
@@ -353,9 +351,9 @@ public class DaoTemplate {
*
* @param where 条件
* @return 数量
* @throws SQLException SQL执行异常
* @throws DbRuntimeException SQL执行异常
*/
public long count(final Entity where) throws SQLException {
public long count(final Entity where) throws DbRuntimeException {
return db.count(fixEntity(where));
}
@@ -364,9 +362,9 @@ public class DaoTemplate {
*
* @param where 条件
* @return 是否存在
* @throws SQLException SQL执行异常
* @throws DbRuntimeException SQL执行异常
*/
public boolean exist(final Entity where) throws SQLException {
public boolean exist(final Entity where) throws DbRuntimeException {
return this.count(where) > 0;
}
//------------------------------------------------------------- Find end

View File

@@ -4,7 +4,6 @@ import cn.hutool.core.lang.func.VoidFunc1;
import cn.hutool.db.dialect.Dialect;
import cn.hutool.db.dialect.DialectFactory;
import cn.hutool.db.ds.DSFactory;
import cn.hutool.db.sql.Wrapper;
import cn.hutool.db.transaction.TransactionLevel;
import cn.hutool.log.StaticLog;
@@ -19,7 +18,7 @@ import java.sql.SQLException;
* @author Looly
* @since 4.1.2
*/
public class Db extends AbstractDb {
public class Db extends AbstractDb<Db> {
private static final long serialVersionUID = -3378415769645309514L;
/**
@@ -28,8 +27,8 @@ public class Db extends AbstractDb {
*
* @return Db
*/
public static Db use() {
return use(DSFactory.get());
public static Db of() {
return of(DSFactory.get());
}
/**
@@ -39,8 +38,8 @@ public class Db extends AbstractDb {
* @param group 数据源分组
* @return Db
*/
public static Db use(final String group) {
return use(DSFactory.get(group));
public static Db of(final String group) {
return of(DSFactory.get(group));
}
/**
@@ -50,7 +49,7 @@ public class Db extends AbstractDb {
* @param ds 数据源
* @return Db
*/
public static Db use(final DataSource ds) {
public static Db of(final DataSource ds) {
return ds == null ? null : new Db(ds);
}
@@ -61,7 +60,7 @@ public class Db extends AbstractDb {
* @param dialect 方言
* @return Db
*/
public static Db use(final DataSource ds, final Dialect dialect) {
public static Db of(final DataSource ds, final Dialect dialect) {
return new Db(ds, dialect);
}
@@ -72,7 +71,7 @@ public class Db extends AbstractDb {
* @param driverClassName 数据库连接驱动类名
* @return Db
*/
public static Db use(final DataSource ds, final String driverClassName) {
public static Db of(final DataSource ds, final String driverClassName) {
return new Db(ds, DialectFactory.newDialect(driverClassName));
}
@@ -107,26 +106,13 @@ public class Db extends AbstractDb {
}
// ---------------------------------------------------------------------------- Constructor end
// ---------------------------------------------------------------------------- Getters and Setters start
@Override
public Db setWrapper(final Character wrapperChar) {
return (Db) super.setWrapper(wrapperChar);
}
@Override
public Db setWrapper(final Wrapper wrapper) {
return (Db) super.setWrapper(wrapper);
}
@Override
public Db disableWrapper() {
return (Db)super.disableWrapper();
}
// ---------------------------------------------------------------------------- Getters and Setters end
@Override
public Connection getConnection() throws SQLException {
return ThreadLocalConnection.INSTANCE.get(this.ds);
public Connection getConnection() throws DbRuntimeException {
try {
return ThreadLocalConnection.INSTANCE.get(this.ds);
} catch (final SQLException e) {
throw new DbRuntimeException(e);
}
}
@Override

View File

@@ -5,9 +5,10 @@ import cn.hutool.core.text.StrUtil;
/**
* 数据库异常
*
* @author xiaoleilu
*/
public class DbRuntimeException extends RuntimeException{
public class DbRuntimeException extends RuntimeException {
private static final long serialVersionUID = 3624487785708765623L;
public DbRuntimeException(final Throwable e) {

View File

@@ -2,8 +2,6 @@ package cn.hutool.db;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.io.IoUtil;
import cn.hutool.db.dialect.Dialect;
import cn.hutool.db.dialect.DialectFactory;
import cn.hutool.db.ds.DSFactory;
import cn.hutool.db.sql.SqlLog;
import cn.hutool.log.Log;
@@ -13,7 +11,6 @@ import cn.hutool.setting.Setting;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.sql.DataSource;
import java.sql.Connection;
/**
* 数据库操作工具类
@@ -23,85 +20,6 @@ import java.sql.Connection;
public final class DbUtil {
private final static Log log = Log.get();
/**
* 实例化一个新的SQL运行对象
*
* @param dialect 数据源
* @return SQL执行类
*/
public static SqlConnRunner newSqlConnRunner(final Dialect dialect) {
return SqlConnRunner.create(dialect);
}
/**
* 实例化一个新的SQL运行对象
*
* @param ds 数据源
* @return SQL执行类
*/
public static SqlConnRunner newSqlConnRunner(final DataSource ds) {
return SqlConnRunner.create(ds);
}
/**
* 实例化一个新的SQL运行对象
*
* @param conn 数据库连接对象
* @return SQL执行类
*/
public static SqlConnRunner newSqlConnRunner(final Connection conn) {
return SqlConnRunner.create(DialectFactory.newDialect(conn));
}
/**
* 实例化一个新的Db使用默认数据源
*
* @return SQL执行类
*/
public static Db use() {
return Db.use();
}
/**
* 实例化一个新的Db对象
*
* @param ds 数据源
* @return SQL执行类
*/
public static Db use(final DataSource ds) {
return Db.use(ds);
}
/**
* 实例化一个新的SQL运行对象
*
* @param ds 数据源
* @param dialect SQL方言
* @return SQL执行类
*/
public static Db use(final DataSource ds, final Dialect dialect) {
return Db.use(ds, dialect);
}
/**
* 新建数据库会话,使用默认数据源
*
* @return 数据库会话
*/
public static Session newSession() {
return Session.create(getDs());
}
/**
* 新建数据库会话
*
* @param ds 数据源
* @return 数据库会话
*/
public static Session newSession(final DataSource ds) {
return Session.create(ds);
}
/**
* 连续关闭一系列的SQL相关对象<br>
* 这些对象必须按照顺序关闭,否则会出错。

View File

@@ -2,11 +2,12 @@ package cn.hutool.db;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.text.StrUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.db.dialect.Dialect;
import cn.hutool.db.dialect.DialectFactory;
import cn.hutool.db.handler.NumberHandler;
import cn.hutool.db.handler.PageResultHandler;
import cn.hutool.db.handler.RsHandler;
import cn.hutool.db.sql.Query;
import cn.hutool.db.sql.SqlBuilder;
@@ -62,9 +63,9 @@ public class DialectRunner implements Serializable {
* @param conn 数据库连接
* @param records 记录列表记录KV必须严格一致
* @return 插入行数
* @throws SQLException SQL执行异常
* @throws DbRuntimeException SQL执行异常
*/
public int[] insert(final Connection conn, final Entity... records) throws SQLException {
public int[] insert(final Connection conn, final Entity... records) throws DbRuntimeException {
checkConn(conn);
if (ArrayUtil.isEmpty(records)) {
return new int[]{0};
@@ -81,6 +82,8 @@ public class DialectRunner implements Serializable {
// 批量
ps = dialect.psForInsertBatch(conn, records);
return ps.executeBatch();
} catch (final SQLException e) {
throw new DbRuntimeException(e);
} finally {
DbUtil.close(ps);
}
@@ -95,19 +98,21 @@ public class DialectRunner implements Serializable {
* @param record 记录
* @param keys 需要检查唯一性的字段
* @return 插入行数
* @throws SQLException SQL执行异常
* @throws DbRuntimeException SQL执行异常
* @since 5.7.20
*/
public int upsert(final Connection conn, final Entity record, final String... keys) throws SQLException {
public int upsert(final Connection conn, final Entity record, final String... keys) throws DbRuntimeException {
PreparedStatement ps = null;
try{
try {
ps = getDialect().psForUpsert(conn, record, keys);
}catch (final SQLException ignore){
} catch (final SQLException ignore) {
// 方言不支持,使用默认
}
if (null != ps) {
try {
return ps.executeUpdate();
} catch (final SQLException e) {
throw new DbRuntimeException(e);
} finally {
DbUtil.close(ps);
}
@@ -124,11 +129,11 @@ public class DialectRunner implements Serializable {
* @param record 记录
* @param keys 需要检查唯一性的字段
* @return 插入行数
* @throws SQLException SQL执行异常
* @throws DbRuntimeException SQL执行异常
*/
public int insertOrUpdate(final Connection conn, final Entity record, final String... keys) throws SQLException {
public int insertOrUpdate(final Connection conn, final Entity record, final String... keys) throws DbRuntimeException {
final Entity where = record.filter(keys);
if (MapUtil.isNotEmpty(where) && count(conn, where) > 0) {
if (MapUtil.isNotEmpty(where) && count(conn, Query.of(where)) > 0) {
return update(conn, record, where);
} else {
return insert(conn, record)[0];
@@ -144,12 +149,12 @@ public class DialectRunner implements Serializable {
* @param record 记录
* @param generatedKeysHandler 自增主键处理器,用于定义返回自增主键的范围和类型
* @return 主键列表
* @throws SQLException SQL执行异常
* @throws DbRuntimeException SQL执行异常
*/
public <T> T insert(final Connection conn, final Entity record, final RsHandler<T> generatedKeysHandler) throws SQLException {
public <T> T insert(final Connection conn, final Entity record, final RsHandler<T> generatedKeysHandler) throws DbRuntimeException {
checkConn(conn);
if (MapUtil.isEmpty(record)) {
throw new SQLException("Empty entity provided!");
throw new DbRuntimeException("Empty entity provided!");
}
PreparedStatement ps = null;
@@ -160,6 +165,8 @@ public class DialectRunner implements Serializable {
return null;
}
return StatementUtil.getGeneratedKeys(ps, generatedKeysHandler);
} catch (final SQLException e) {
throw new DbRuntimeException(e);
} finally {
DbUtil.close(ps);
}
@@ -172,19 +179,21 @@ public class DialectRunner implements Serializable {
* @param conn 数据库连接
* @param where 条件
* @return 影响行数
* @throws SQLException SQL执行异常
* @throws DbRuntimeException SQL执行异常
*/
public int del(final Connection conn, final Entity where) throws SQLException {
public int del(final Connection conn, final Entity where) throws DbRuntimeException {
checkConn(conn);
if (MapUtil.isEmpty(where)) {
//不允许做全表删除
throw new SQLException("Empty entity provided!");
throw new DbRuntimeException("Empty entity provided!");
}
PreparedStatement ps = null;
try {
ps = dialect.psForDelete(conn, Query.of(where));
return ps.executeUpdate();
} catch (final SQLException e) {
throw new DbRuntimeException(e);
} finally {
DbUtil.close(ps);
}
@@ -198,16 +207,16 @@ public class DialectRunner implements Serializable {
* @param record 记录
* @param where 条件
* @return 影响行数
* @throws SQLException SQL执行异常
* @throws DbRuntimeException SQL执行异常
*/
public int update(final Connection conn, final Entity record, final Entity where) throws SQLException {
public int update(final Connection conn, final Entity record, final Entity where) throws DbRuntimeException {
checkConn(conn);
if (MapUtil.isEmpty(record)) {
throw new SQLException("Empty entity provided!");
throw new DbRuntimeException("Empty entity provided!");
}
if (MapUtil.isEmpty(where)) {
//不允许做全表更新
throw new SQLException("Empty where provided!");
throw new DbRuntimeException("Empty where provided!");
}
//表名可以从被更新记录的Entity中获得也可以从Where中获得
@@ -222,6 +231,8 @@ public class DialectRunner implements Serializable {
try {
ps = dialect.psForUpdate(conn, record, query);
return ps.executeUpdate();
} catch (final SQLException e) {
throw new DbRuntimeException(e);
} finally {
DbUtil.close(ps);
}
@@ -236,25 +247,33 @@ public class DialectRunner implements Serializable {
* @param query {@link Query}
* @param rsh 结果集处理对象
* @return 结果对象
* @throws SQLException SQL执行异常
* @throws DbRuntimeException SQL执行异常
*/
public <T> T find(final Connection conn, final Query query, final RsHandler<T> rsh) throws SQLException {
public <T> T find(final Connection conn, final Query query, final RsHandler<T> rsh) throws DbRuntimeException {
checkConn(conn);
Assert.notNull(query, "[query] is null !");
return SqlExecutor.queryAndClosePs(dialect.psForFind(conn, query), rsh);
try {
return SqlExecutor.queryAndClosePs(dialect.psForFind(conn, query), rsh);
} catch (final SQLException e) {
throw new DbRuntimeException(e);
}
}
/**
* 获取结果总数生成类似于select count(1) from XXX wher XXX=? and YYY=?
*
* @param conn 数据库连接对象
* @param where 查询条件
* @param query 查询
* @return 复合条件的结果数
* @throws SQLException SQL执行异常
* @throws DbRuntimeException SQL执行异常
*/
public long count(final Connection conn, final Entity where) throws SQLException {
public long count(final Connection conn, final Query query) throws DbRuntimeException {
checkConn(conn);
return SqlExecutor.queryAndClosePs(dialect.psForCount(conn, Query.of(where)), new NumberHandler()).longValue();
try {
return SqlExecutor.queryAndClosePs(dialect.psForCount(conn, query), new NumberHandler()).longValue();
} catch (final SQLException e) {
throw new DbRuntimeException(e);
}
}
/**
@@ -264,10 +283,10 @@ public class DialectRunner implements Serializable {
* @param conn 数据库连接对象
* @param sqlBuilder 查询语句
* @return 复合条件的结果数
* @throws SQLException SQL执行异常
* @throws DbRuntimeException SQL执行异常
* @since 5.7.2
*/
public long count(final Connection conn, final SqlBuilder sqlBuilder) throws SQLException {
public long count(final Connection conn, final SqlBuilder sqlBuilder) throws DbRuntimeException {
checkConn(conn);
String selectSql = sqlBuilder.build();
@@ -276,9 +295,30 @@ public class DialectRunner implements Serializable {
if (orderByIndex > 0) {
selectSql = StrUtil.subPre(selectSql, orderByIndex);
}
return SqlExecutor.queryAndClosePs(dialect.psForCount(conn,
SqlBuilder.of(selectSql).addParams(sqlBuilder.getParamValueArray())),
new NumberHandler()).longValue();
try {
return SqlExecutor.queryAndClosePs(dialect.psForCount(conn,
SqlBuilder.of(selectSql).addParams(sqlBuilder.getParamValueArray())),
new NumberHandler()).longValue();
} catch (final SQLException e) {
throw new DbRuntimeException(e);
}
}
/**
* 分页查询<br>
* 此方法不会关闭Connection
*
* @param conn 数据库连接对象
* @param query 查询
* @return 结果对象
* @throws DbRuntimeException SQL执行异常
*/
public PageResult<Entity> page(final Connection conn, final Query query) throws DbRuntimeException {
final Page page = query.getPage();
final PageResultHandler pageResultHandler = new PageResultHandler(
new PageResult<>(page.getPageNumber(), page.getPageSize(), (int) count(conn, query)),
this.caseInsensitive);
return page(conn, query, pageResultHandler);
}
/**
@@ -290,15 +330,36 @@ public class DialectRunner implements Serializable {
* @param query 查询条件(包含表名)
* @param rsh 结果集处理对象
* @return 结果对象
* @throws SQLException SQL执行异常
* @throws DbRuntimeException SQL执行异常
*/
public <T> T page(final Connection conn, final Query query, final RsHandler<T> rsh) throws SQLException {
public <T> T page(final Connection conn, final Query query, final RsHandler<T> rsh) throws DbRuntimeException {
checkConn(conn);
if (null == query.getPage()) {
return this.find(conn, query, rsh);
}
return SqlExecutor.queryAndClosePs(dialect.psForPage(conn, query), rsh);
try {
return SqlExecutor.queryAndClosePs(dialect.psForPage(conn, query), rsh);
} catch (final SQLException e) {
throw new DbRuntimeException(e);
}
}
/**
* 分页查询<br>
* 此方法不会关闭Connection
*
* @param conn 数据库连接对象
* @param sqlBuilder SQL构建器可以使用{@link SqlBuilder#of(CharSequence)} 包装普通SQL
* @param page 分页对象
* @return 结果对象
* @throws DbRuntimeException SQL执行异常
*/
public PageResult<Entity> page(final Connection conn, final SqlBuilder sqlBuilder, final Page page) throws DbRuntimeException {
final PageResultHandler pageResultHandler = new PageResultHandler(
new PageResult<>(page.getPageNumber(), page.getPageSize(), (int) count(conn, sqlBuilder)),
this.caseInsensitive);
return page(conn, sqlBuilder, page, pageResultHandler);
}
/**
@@ -311,16 +372,22 @@ public class DialectRunner implements Serializable {
* @param page 分页对象
* @param rsh 结果集处理对象
* @return 结果对象
* @throws SQLException SQL执行异常
* @throws DbRuntimeException SQL执行异常
* @since 5.5.3
*/
public <T> T page(final Connection conn, final SqlBuilder sqlBuilder, final Page page, final RsHandler<T> rsh) throws SQLException {
public <T> T page(final Connection conn, final SqlBuilder sqlBuilder, final Page page, final RsHandler<T> rsh) throws DbRuntimeException {
checkConn(conn);
if (null == page) {
return SqlExecutor.query(conn, sqlBuilder, rsh);
}
return SqlExecutor.queryAndClosePs(dialect.psForPage(conn, sqlBuilder, page), rsh);
final PreparedStatement ps;
try {
ps = dialect.psForPage(conn, sqlBuilder, page);
} catch (final SQLException e) {
throw new DbRuntimeException(e);
}
return SqlExecutor.queryAndClosePs(ps, rsh);
}
//---------------------------------------------------------------------------- CRUD end

View File

@@ -5,7 +5,6 @@ import cn.hutool.core.text.StrUtil;
import cn.hutool.db.dialect.Dialect;
import cn.hutool.db.dialect.DialectFactory;
import cn.hutool.db.ds.DSFactory;
import cn.hutool.db.sql.Wrapper;
import cn.hutool.log.Log;
import cn.hutool.log.LogFactory;
@@ -24,7 +23,7 @@ import java.sql.Savepoint;
* @author loolly
*
*/
public class Session extends AbstractDb implements Closeable {
public class Session extends AbstractDb<Session> implements Closeable {
private static final long serialVersionUID = 3421251905539056945L;
private final static Log log = LogFactory.get();
@@ -34,7 +33,7 @@ public class Session extends AbstractDb implements Closeable {
* @return Session
* @since 3.2.3
*/
public static Session create() {
public static Session of() {
return new Session(DSFactory.get());
}
@@ -45,7 +44,7 @@ public class Session extends AbstractDb implements Closeable {
* @return Session
* @since 4.0.11
*/
public static Session create(final String group) {
public static Session of(final String group) {
return new Session(DSFactory.get(group));
}
@@ -55,7 +54,7 @@ public class Session extends AbstractDb implements Closeable {
* @param ds 数据源
* @return Session
*/
public static Session create(final DataSource ds) {
public static Session of(final DataSource ds) {
return new Session(ds);
}
@@ -90,38 +89,32 @@ public class Session extends AbstractDb implements Closeable {
}
// ---------------------------------------------------------------------------- Constructor end
// ---------------------------------------------------------------------------- Getters and Setters end
/**
* 获得{@link SqlConnRunner}
*
* @return {@link SqlConnRunner}
*/
@Override
public SqlConnRunner getRunner() {
return runner;
}
// ---------------------------------------------------------------------------- Getters and Setters end
// ---------------------------------------------------------------------------- Transaction method start
/**
* 开始事务
*
* @throws SQLException SQL执行异常
* @throws DbRuntimeException SQL执行异常
*/
public void beginTransaction() throws SQLException {
public void beginTransaction() throws DbRuntimeException {
final Connection conn = getConnection();
checkTransactionSupported(conn);
conn.setAutoCommit(false);
try {
conn.setAutoCommit(false);
} catch (final SQLException e) {
throw new DbRuntimeException(e);
}
}
/**
* 提交事务
*
* @throws SQLException SQL执行异常
* @throws DbRuntimeException SQL执行异常
*/
public void commit() throws SQLException {
public void commit() throws DbRuntimeException {
try {
getConnection().commit();
} catch (final SQLException e) {
throw new DbRuntimeException(e);
} finally {
try {
getConnection().setAutoCommit(true); // 事务结束,恢复自动提交
@@ -134,11 +127,13 @@ public class Session extends AbstractDb implements Closeable {
/**
* 回滚事务
*
* @throws SQLException SQL执行异常
* @throws DbRuntimeException SQL执行异常
*/
public void rollback() throws SQLException {
public void rollback() throws DbRuntimeException {
try {
getConnection().rollback();
} catch (final SQLException e) {
throw new DbRuntimeException(e);
} finally {
try {
getConnection().setAutoCommit(true); // 事务结束,恢复自动提交
@@ -170,11 +165,13 @@ public class Session extends AbstractDb implements Closeable {
* 回滚到某个保存点保存点的设置请使用setSavepoint方法
*
* @param savepoint 保存点
* @throws SQLException SQL执行异常
* @throws DbRuntimeException SQL执行异常
*/
public void rollback(final Savepoint savepoint) throws SQLException {
public void rollback(final Savepoint savepoint) throws DbRuntimeException {
try {
getConnection().rollback(savepoint);
} catch (final SQLException e) {
throw new DbRuntimeException(e);
} finally {
try {
getConnection().setAutoCommit(true); // 事务结束,恢复自动提交
@@ -207,10 +204,14 @@ public class Session extends AbstractDb implements Closeable {
* 设置保存点
*
* @return 保存点对象
* @throws SQLException SQL执行异常
* @throws DbRuntimeException SQL执行异常
*/
public Savepoint setSavepoint() throws SQLException {
return getConnection().setSavepoint();
public Savepoint setSavepoint() throws DbRuntimeException {
try {
return getConnection().setSavepoint();
} catch (final SQLException e) {
throw new DbRuntimeException(e);
}
}
/**
@@ -234,55 +235,46 @@ public class Session extends AbstractDb implements Closeable {
* Connection.TRANSACTION_SERIALIZABLE 禁止脏读、不可重复读和幻读<br>
*
* @param level 隔离级别
* @throws SQLException SQL执行异常
* @throws DbRuntimeException SQL执行异常
*/
public void setTransactionIsolation(final int level) throws SQLException {
if (getConnection().getMetaData().supportsTransactionIsolationLevel(level) == false) {
throw new SQLException(StrUtil.format("Transaction isolation [{}] not support!", level));
public void setTransactionIsolation(final int level) throws DbRuntimeException {
try {
if (getConnection().getMetaData().supportsTransactionIsolationLevel(level) == false) {
throw new DbRuntimeException(StrUtil.format("Transaction isolation [{}] not support!", level));
}
getConnection().setTransactionIsolation(level);
} catch (final SQLException e) {
throw new DbRuntimeException(e);
}
getConnection().setTransactionIsolation(level);
}
/**
* 在事务中执行操作,通过实现{@link VoidFunc1}接口的call方法执行多条SQL语句从而完成事务
*
* @param func 函数抽象在函数中执行多个SQL操作多个操作会被合并为同一事务
* @throws SQLException SQL异常
* @throws DbRuntimeException SQL异常
* @since 3.2.3
*/
public void tx(final VoidFunc1<Session> func) throws SQLException {
public void tx(final VoidFunc1<Session> func) throws DbRuntimeException {
try {
beginTransaction();
func.call(this);
commit();
} catch (final Throwable e) {
quietRollback();
throw (e instanceof SQLException) ? (SQLException) e : new SQLException(e);
throw new DbRuntimeException(e);
}
}
// ---------------------------------------------------------------------------- Transaction method end
// ---------------------------------------------------------------------------- Getters and Setters start
@Override
public Session setWrapper(final Character wrapperChar) {
return (Session) super.setWrapper(wrapperChar);
}
@Override
public Session setWrapper(final Wrapper wrapper) {
return (Session) super.setWrapper(wrapper);
}
@Override
public Session disableWrapper() {
return (Session) super.disableWrapper();
}
// ---------------------------------------------------------------------------- Getters and Setters end
@Override
public Connection getConnection() throws SQLException {
return ThreadLocalConnection.INSTANCE.get(this.ds);
public Connection getConnection() throws DbRuntimeException {
try {
return ThreadLocalConnection.INSTANCE.get(this.ds);
} catch (final SQLException e) {
throw new RuntimeException(e);
}
}
@Override

View File

@@ -1,376 +0,0 @@
package cn.hutool.db;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.db.dialect.Dialect;
import cn.hutool.db.dialect.DialectFactory;
import cn.hutool.db.handler.EntityListHandler;
import cn.hutool.db.handler.HandleHelper;
import cn.hutool.db.handler.PageResultHandler;
import cn.hutool.db.handler.RsHandler;
import cn.hutool.db.sql.Condition.LikeType;
import cn.hutool.db.sql.Query;
import cn.hutool.db.sql.SqlBuilder;
import cn.hutool.db.sql.SqlUtil;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Collection;
import java.util.List;
/**
* SQL执行类<br>
* 此执行类只接受方言参数,不需要数据源,只有在执行方法时需要数据库连接对象<br>
* 此对象存在的意义在于,可以由使用者自定义数据库连接对象,并执行多个方法,方便事务的统一控制或减少连接对象的创建关闭<br>
* 相比{@link DialectRunner},此类中提供了更多重载方法
*
* @author Luxiaolei
*/
public class SqlConnRunner extends DialectRunner {
private static final long serialVersionUID = 1L;
/**
* 实例化一个新的SQL运行对象
*
* @param dialect 方言
* @return SQL执行类
*/
public static SqlConnRunner create(final Dialect dialect) {
return new SqlConnRunner(dialect);
}
/**
* 实例化一个新的SQL运行对象
*
* @param ds 数据源
* @return SQL执行类
*/
public static SqlConnRunner create(final DataSource ds) {
return new SqlConnRunner(DialectFactory.getDialect(ds));
}
/**
* 实例化一个新的SQL运行对象
*
* @param driverClassName 驱动类名
* @return SQL执行类
*/
public static SqlConnRunner create(final String driverClassName) {
return new SqlConnRunner(driverClassName);
}
//------------------------------------------------------- Constructor start
/**
* 构造
*
* @param dialect 方言
*/
public SqlConnRunner(final Dialect dialect) {
super(dialect);
}
/**
* 构造
*
* @param driverClassName 驱动类名,用于识别方言
*/
public SqlConnRunner(final String driverClassName) {
super(driverClassName);
}
//------------------------------------------------------- Constructor end
//---------------------------------------------------------------------------- CRUD start
/**
* 批量插入数据<br>
* 需要注意的是,批量插入每一条数据结构必须一致。批量插入数据时会获取第一条数据的字段结构,之后的数据会按照这个格式插入。<br>
* 也就是说假如第一条数据只有2个字段后边数据多于这两个字段的部分将被抛弃。
* 此方法不会关闭Connection
*
* @param conn 数据库连接
* @param records 记录列表记录KV必须严格一致
* @return 插入行数
* @throws SQLException SQL执行异常
*/
public int[] insert(final Connection conn, final Collection<Entity> records) throws SQLException {
return insert(conn, records.toArray(new Entity[0]));
}
/**
* 插入数据<br>
* 此方法不会关闭Connection
*
* @param conn 数据库连接
* @param record 记录
* @return 插入行数
* @throws SQLException SQL执行异常
*/
public int insert(final Connection conn, final Entity record) throws SQLException {
return insert(conn, new Entity[]{record})[0];
}
/**
* 插入数据<br>
* 此方法不会关闭Connection
*
* @param conn 数据库连接
* @param record 记录
* @return 主键列表
* @throws SQLException SQL执行异常
*/
public List<Object> insertForGeneratedKeys(final Connection conn, final Entity record) throws SQLException {
return insert(conn, record, HandleHelper::handleRowToList);
}
/**
* 插入数据<br>
* 此方法不会关闭Connection
*
* @param conn 数据库连接
* @param record 记录
* @return 自增主键
* @throws SQLException SQL执行异常
*/
public Long insertForGeneratedKey(final Connection conn, final Entity record) throws SQLException {
return insert(conn, record, (rs) -> {
Long generatedKey = null;
if (rs != null && rs.next()) {
try {
generatedKey = rs.getLong(1);
} catch (final SQLException e) {
// 自增主键不为数字或者为Oracle的rowid跳过
}
}
return generatedKey;
});
}
/**
* 查询<br>
* 此方法不会关闭Connection
*
* @param <T> 结果对象类型
* @param conn 数据库连接对象
* @param fields 返回的字段列表null则返回所有字段
* @param where 条件实体类(包含表名)
* @param rsh 结果集处理对象
* @return 结果对象
* @throws SQLException SQL执行异常
*/
public <T> T find(final Connection conn, final Collection<String> fields, final Entity where, final RsHandler<T> rsh) throws SQLException {
return find(conn, Query.of(where).setFields(fields), rsh);
}
/**
* 查询,返回指定字段列表<br>
* 此方法不会关闭Connection
*
* @param <T> 结果对象类型
* @param conn 数据库连接对象
* @param where 条件实体类(包含表名)
* @param rsh 结果集处理对象
* @param fields 字段列表,可变长参数如果无值表示查询全部字段
* @return 结果对象
* @throws SQLException SQL执行异常
*/
public <T> T find(final Connection conn, final Entity where, final RsHandler<T> rsh, final String... fields) throws SQLException {
return find(conn, CollUtil.newArrayList(fields), where, rsh);
}
/**
* 查询数据列表返回字段在where参数中定义
*
* @param conn 数据库连接对象
* @param where 条件实体类(包含表名)
* @return 数据对象列表
* @throws SQLException SQL执行异常
* @since 3.2.1
*/
public List<Entity> find(final Connection conn, final Entity where) throws SQLException {
return find(conn, where.getFieldNames(), where, new EntityListHandler(this.caseInsensitive));
}
/**
* 查询数据列表,返回所有字段
*
* @param conn 数据库连接对象
* @param where 条件实体类(包含表名)
* @return 数据对象列表
* @throws SQLException SQL执行异常
*/
public List<Entity> findAll(final Connection conn, final Entity where) throws SQLException {
return find(conn, where, new EntityListHandler(this.caseInsensitive));
}
/**
* 查询数据列表,返回所有字段
*
* @param conn 数据库连接对象
* @param tableName 表名
* @return 数据对象列表
* @throws SQLException SQL执行异常
*/
public List<Entity> findAll(final Connection conn, final String tableName) throws SQLException {
return findAll(conn, Entity.create(tableName));
}
/**
* 根据某个字段名条件查询数据列表,返回所有字段
*
* @param conn 数据库连接对象
* @param tableName 表名
* @param field 字段名
* @param value 字段值
* @return 数据对象列表
* @throws SQLException SQL执行异常
*/
public List<Entity> findBy(final Connection conn, final String tableName, final String field, final Object value) throws SQLException {
return findAll(conn, Entity.create(tableName).set(field, value));
}
/**
* 根据某个字段名条件查询数据列表,返回所有字段
*
* @param conn 数据库连接对象
* @param tableName 表名
* @param field 字段名
* @param value 字段值
* @param likeType {@link LikeType}
* @return 数据对象列表
* @throws SQLException SQL执行异常
*/
public List<Entity> findLike(final Connection conn, final String tableName, final String field, final String value, final LikeType likeType) throws SQLException {
return findAll(conn, Entity.create(tableName).set(field, SqlUtil.buildLikeValue(value, likeType, true)));
}
/**
* 根据某个字段名条件查询数据列表,返回所有字段
*
* @param conn 数据库连接对象
* @param tableName 表名
* @param field 字段名
* @param values 字段值列表
* @return 数据对象列表
* @throws SQLException SQL执行异常
*/
public List<Entity> findIn(final Connection conn, final String tableName, final String field, final Object... values) throws SQLException {
return findAll(conn, Entity.create(tableName).set(field, values));
}
/**
* 获取查询结果总数,生成类似于 SELECT count(1) from (sql) as _count
*
* @param conn 数据库连接对象
* @param selectSql 查询语句
* @param params 查询参数
* @return 结果数
* @throws SQLException SQL异常
* @since 5.6.6
*/
public long count(final Connection conn, final CharSequence selectSql, final Object... params) throws SQLException {
return count(conn, SqlBuilder.of(selectSql).addParams(params));
}
/**
* 分页查询<br>
* 此方法不会关闭Connection
*
* @param <T> 结果对象类型
* @param conn 数据库连接对象
* @param fields 返回的字段列表null则返回所有字段
* @param where 条件实体类(包含表名)
* @param pageNumber 页码
* @param numPerPage 每页条目数
* @param rsh 结果集处理对象
* @return 结果对象
* @throws SQLException SQL执行异常
*/
public <T> T page(final Connection conn, final Collection<String> fields, final Entity where, final int pageNumber, final int numPerPage, final RsHandler<T> rsh) throws SQLException {
return page(conn, Query.of(where).setFields(fields).setPage(new Page(pageNumber, numPerPage)), rsh);
}
/**
* 分页查询<br>
* 此方法不会关闭Connection
*
* @param conn 数据库连接对象
* @param sqlBuilder SQL构建器可以使用{@link SqlBuilder#of(CharSequence)} 包装普通SQL
* @param page 分页对象
* @return 结果对象
* @throws SQLException SQL执行异常
* @since 5.5.3
*/
public PageResult<Entity> page(final Connection conn, final SqlBuilder sqlBuilder, final Page page) throws SQLException {
final PageResultHandler pageResultHandler = new PageResultHandler(
new PageResult<>(page.getPageNumber(), page.getPageSize(), (int) count(conn, sqlBuilder)),
this.caseInsensitive);
return page(conn, sqlBuilder, page, pageResultHandler);
}
/**
* 分页查询<br>
* 此方法不会关闭Connection
*
* @param conn 数据库连接对象
* @param fields 返回的字段列表null则返回所有字段
* @param where 条件实体类(包含表名)
* @param page 页码
* @param numPerPage 每页条目数
* @return 结果对象
* @throws SQLException SQL执行异常
*/
public PageResult<Entity> page(final Connection conn, final Collection<String> fields, final Entity where, final int page, final int numPerPage) throws SQLException {
return page(conn, fields, where, new Page(page, numPerPage));
}
/**
* 分页全字段查询<br>
* 此方法不会关闭Connection
*
* @param conn 数据库连接对象
* @param where 条件实体类(包含表名)
* @param page 分页对象
* @return 结果对象
* @throws SQLException SQL执行异常
*/
public PageResult<Entity> page(final Connection conn, final Entity where, final Page page) throws SQLException {
return this.page(conn, null, where, page);
}
/**
* 分页查询<br>
* 此方法不会关闭Connection
*
* @param conn 数据库连接对象
* @param fields 返回的字段列表null则返回所有字段
* @param where 条件实体类(包含表名)
* @param page 分页对象
* @return 结果对象
* @throws SQLException SQL执行异常
*/
public PageResult<Entity> page(final Connection conn, final Collection<String> fields, final Entity where, final Page page) throws SQLException {
final PageResultHandler pageResultHandler = new PageResultHandler(
new PageResult<>(page.getPageNumber(), page.getPageSize(), (int) count(conn, where)),
this.caseInsensitive);
return page(conn, fields, where, page, pageResultHandler);
}
/**
* 分页查询<br>
* 此方法不会关闭Connection
*
* @param <T> 结果类型,取决于 {@link RsHandler} 的处理逻辑
* @param conn 数据库连接对象
* @param fields 返回的字段列表null则返回所有字段
* @param where 条件实体类(包含表名)
* @param page 分页对象
* @param handler 结果集处理器
* @return 结果对象
* @throws SQLException SQL执行异常
*/
public <T> T page(final Connection conn, final Collection<String> fields, final Entity where, final Page page, final RsHandler<T> handler) throws SQLException {
return this.page(conn, Query.of(where).setFields(fields).setPage(page), handler);
}
//---------------------------------------------------------------------------- CRUD end
}

View File

@@ -6,7 +6,7 @@ import cn.hutool.core.convert.Convert;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.text.StrUtil;
import cn.hutool.db.handler.HandleHelper;
import cn.hutool.db.handler.ResultSetUtil;
import cn.hutool.db.handler.RsHandler;
import cn.hutool.db.sql.NamedSql;
import cn.hutool.db.sql.SqlBuilder;
@@ -259,7 +259,7 @@ public class StatementUtil {
* @throws SQLException SQL执行异常
*/
public static List<Object> getGeneratedKeys(final Statement ps) throws SQLException {
return getGeneratedKeys(ps, HandleHelper::handleRowToList);
return getGeneratedKeys(ps, ResultSetUtil::handleRowToList);
}
/**

View File

@@ -35,6 +35,6 @@ public class BeanHandler<E> implements RsHandler<E>{
public E handle(final ResultSet rs) throws SQLException {
final ResultSetMetaData meta = rs.getMetaData();
final int columnCount = meta.getColumnCount();
return rs.next() ? HandleHelper.handleRow(columnCount, meta, rs, this.elementBeanType) : null;
return rs.next() ? ResultSetUtil.toBean(columnCount, meta, rs, this.elementBeanType) : null;
}
}

View File

@@ -38,6 +38,6 @@ public class BeanListHandler<E> implements RsHandler<List<E>> {
@Override
public List<E> handle(final ResultSet rs) throws SQLException {
return HandleHelper.handleRsToBeanList(rs, new ArrayList<>(), elementBeanType);
return ResultSetUtil.toBeanList(rs, new ArrayList<>(), elementBeanType);
}
}

View File

@@ -47,6 +47,6 @@ public class EntityHandler implements RsHandler<Entity>{
final ResultSetMetaData meta = rs.getMetaData();
final int columnCount = meta.getColumnCount();
return rs.next() ? HandleHelper.handleRow(columnCount, meta, rs, this.caseInsensitive) : null;
return rs.next() ? ResultSetUtil.toBean(columnCount, meta, rs, this.caseInsensitive) : null;
}
}

View File

@@ -44,6 +44,6 @@ public class EntityListHandler implements RsHandler<List<Entity>>{
@Override
public List<Entity> handle(final ResultSet rs) throws SQLException {
return HandleHelper.handleRs(rs, new ArrayList<>(), this.caseInsensitive);
return ResultSetUtil.toEntityList(rs, new ArrayList<>(), this.caseInsensitive);
}
}

View File

@@ -43,6 +43,6 @@ public class EntitySetHandler implements RsHandler<LinkedHashSet<Entity>>{
@Override
public LinkedHashSet<Entity> handle(final ResultSet rs) throws SQLException {
return HandleHelper.handleRs(rs, new LinkedHashSet<>(), this.caseInsensitive);
return ResultSetUtil.toEntityList(rs, new LinkedHashSet<>(), this.caseInsensitive);
}
}

View File

@@ -55,6 +55,6 @@ public class PageResultHandler implements RsHandler<PageResult<Entity>> {
@Override
public PageResult<Entity> handle(final ResultSet rs) throws SQLException {
return HandleHelper.handleRs(rs, pageResult, this.caseInsensitive);
return ResultSetUtil.toEntityList(rs, pageResult, this.caseInsensitive);
}
}

View File

@@ -8,6 +8,7 @@ import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.reflect.ReflectUtil;
import cn.hutool.core.text.StrUtil;
import cn.hutool.core.reflect.TypeUtil;
import cn.hutool.db.DbRuntimeException;
import cn.hutool.db.Entity;
import java.lang.reflect.Method;
@@ -24,61 +25,60 @@ import java.util.Map;
/**
* 数据结果集处理辅助类
*
* @author loolly
*
* @author looly
*/
public class HandleHelper {
public class ResultSetUtil {
/**
* 处理单条数据
*
* @param <T> Bean类型
* @param <T> Bean类型
* @param columnCount 列数
* @param meta ResultSetMetaData
* @param rs 数据集
* @param bean 目标Bean
* @param meta ResultSetMetaData
* @param rs 数据集
* @param bean 目标Bean
* @return 每一行的Entity
* @throws SQLException SQL执行异常
* @since 3.3.1
*/
public static <T> T handleRow(final int columnCount, final ResultSetMetaData meta, final ResultSet rs, final T bean) throws SQLException {
return handleRow(columnCount, meta, rs).toBeanIgnoreCase(bean);
public static <T> T toBean(final int columnCount, final ResultSetMetaData meta, final ResultSet rs, final T bean) throws SQLException {
return toEntity(columnCount, meta, rs).toBeanIgnoreCase(bean);
}
/**
* 处理单条数据
*
* @param <T> Bean类型
* @param <T> Bean类型
* @param columnCount 列数
* @param meta ResultSetMetaData
* @param rs 数据集
* @param beanClass 目标Bean类型
* @param meta ResultSetMetaData
* @param rs 数据集
* @param beanClass 目标Bean类型
* @return 每一行的Entity
* @throws SQLException SQL执行异常
* @since 3.3.1
*/
@SuppressWarnings("unchecked")
public static <T> T handleRow(final int columnCount, final ResultSetMetaData meta, final ResultSet rs, final Class<T> beanClass) throws SQLException {
public static <T> T toBean(final int columnCount, final ResultSetMetaData meta, final ResultSet rs, final Class<T> beanClass) throws SQLException {
Assert.notNull(beanClass, "Bean Class must be not null !");
if(beanClass.isArray()) {
if (beanClass.isArray()) {
//返回数组
final Class<?> componentType = beanClass.getComponentType();
final Object[] result = ArrayUtil.newArray(componentType, columnCount);
for(int i = 0,j = 1; i < columnCount; i++, j++) {
for (int i = 0, j = 1; i < columnCount; i++, j++) {
result[i] = getColumnValue(rs, j, meta.getColumnType(j), componentType);
}
return (T) result;
} else if(Iterable.class.isAssignableFrom(beanClass)) {
} else if (Iterable.class.isAssignableFrom(beanClass)) {
//集合
final Object[] objRow = handleRow(columnCount, meta, rs, Object[].class);
final Object[] objRow = toBean(columnCount, meta, rs, Object[].class);
return Convert.convert(beanClass, objRow);
} else if(beanClass.isAssignableFrom(Entity.class)) {
} else if (beanClass.isAssignableFrom(Entity.class)) {
//Entity的父类都可按照Entity返回
return (T) handleRow(columnCount, meta, rs);
} else if(String.class == beanClass) {
return (T) toEntity(columnCount, meta, rs);
} else if (String.class == beanClass) {
//字符串
final Object[] objRow = handleRow(columnCount, meta, rs, Object[].class);
final Object[] objRow = toBean(columnCount, meta, rs, Object[].class);
return (T) StrUtil.join(", ", objRow);
}
@@ -93,13 +93,13 @@ public class HandleHelper {
for (int i = 1; i <= columnCount; i++) {
columnLabel = meta.getColumnLabel(i);
pd = propMap.get(columnLabel);
if(null == pd) {
if (null == pd) {
// 尝试驼峰命名风格
pd = propMap.get(StrUtil.toCamelCase(columnLabel));
}
setter = (null == pd) ? null : pd.getSetter();
if(null != setter) {
value = getColumnValue(rs, i, meta.getColumnType(i), TypeUtil.getFirstParamType(setter));
if (null != setter) {
value = getColumnValue(rs, i, meta.getColumnType(i), TypeUtil.getFirstParamType(setter));
ReflectUtil.invokeWithCheck(bean, setter, value);
}
}
@@ -110,44 +110,44 @@ public class HandleHelper {
* 处理单条数据
*
* @param columnCount 列数
* @param meta ResultSetMetaData
* @param rs 数据集
* @param meta ResultSetMetaData
* @param rs 数据集
* @return 每一行的Entity
* @throws SQLException SQL执行异常
*/
public static Entity handleRow(final int columnCount, final ResultSetMetaData meta, final ResultSet rs) throws SQLException {
return handleRow(columnCount, meta, rs, false);
public static Entity toEntity(final int columnCount, final ResultSetMetaData meta, final ResultSet rs) throws SQLException {
return toBean(columnCount, meta, rs, false);
}
/**
* 处理单条数据
*
* @param columnCount 列数
* @param meta ResultSetMetaData
* @param rs 数据集
* @param columnCount 列数
* @param meta ResultSetMetaData
* @param rs 数据集
* @param caseInsensitive 是否大小写不敏感
* @return 每一行的Entity
* @throws SQLException SQL执行异常
* @since 4.5.16
*/
public static Entity handleRow(final int columnCount, final ResultSetMetaData meta, final ResultSet rs, final boolean caseInsensitive) throws SQLException {
return handleRow(new Entity(null, caseInsensitive), columnCount, meta, rs, true);
public static Entity toBean(final int columnCount, final ResultSetMetaData meta, final ResultSet rs, final boolean caseInsensitive) throws SQLException {
return toBean(new Entity(null, caseInsensitive), columnCount, meta, rs, true);
}
/**
* 处理单条数据
*
* @param <T> Entity及其子对象
* @param row Entity对象
* @param columnCount 列数
* @param meta ResultSetMetaData
* @param rs 数据集
* @param <T> Entity及其子对象
* @param row Entity对象
* @param columnCount 列数
* @param meta ResultSetMetaData
* @param rs 数据集
* @param withMetaInfo 是否包含表名字段名等元信息
* @return 每一行的Entity
* @throws SQLException SQL执行异常
* @since 3.3.1
*/
public static <T extends Entity> T handleRow(final T row, final int columnCount, final ResultSetMetaData meta, final ResultSet rs, final boolean withMetaInfo) throws SQLException {
public static <T extends Entity> T toBean(final T row, final int columnCount, final ResultSetMetaData meta, final ResultSet rs, final boolean withMetaInfo) throws SQLException {
int type;
for (int i = 1; i <= columnCount; i++) {
type = meta.getColumnType(i);
@@ -156,7 +156,7 @@ public class HandleHelper {
if (withMetaInfo) {
try {
row.setTableName(meta.getTableName(1));
} catch (final SQLException ignore){
} catch (final SQLException ignore) {
//issue#I2AGLU@Gitee
// Hive等NoSQL中无表的概念此处报错跳过
}
@@ -172,10 +172,10 @@ public class HandleHelper {
* @return 每一行的Entity
* @throws SQLException SQL执行异常
*/
public static Entity handleRow(final ResultSet rs) throws SQLException {
public static Entity toEntity(final ResultSet rs) throws SQLException {
final ResultSetMetaData meta = rs.getMetaData();
final int columnCount = meta.getColumnCount();
return handleRow(columnCount, meta, rs);
return toEntity(columnCount, meta, rs);
}
/**
@@ -200,33 +200,33 @@ public class HandleHelper {
/**
* 处理多条数据
*
* @param <T> 集合类型
* @param rs 数据集
* @param <T> 集合类型
* @param rs 数据集
* @param collection 数据集
* @return Entity列表
* @throws SQLException SQL执行异常
*/
public static <T extends Collection<Entity>> T handleRs(final ResultSet rs, final T collection) throws SQLException {
return handleRs(rs, collection, false);
public static <T extends Collection<Entity>> T toEntityList(final ResultSet rs, final T collection) throws SQLException {
return toEntityList(rs, collection, false);
}
/**
* 处理多条数据
*
* @param <T> 集合类型
* @param rs 数据集
* @param collection 数据集
* @param <T> 集合类型
* @param rs 数据集
* @param collection 数据集
* @param caseInsensitive 是否大小写不敏感
* @return Entity列表
* @throws SQLException SQL执行异常
* @since 4.5.16
*/
public static <T extends Collection<Entity>> T handleRs(final ResultSet rs, final T collection, final boolean caseInsensitive) throws SQLException {
public static <T extends Collection<Entity>> T toEntityList(final ResultSet rs, final T collection, final boolean caseInsensitive) throws SQLException {
final ResultSetMetaData meta = rs.getMetaData();
final int columnCount = meta.getColumnCount();
while (rs.next()) {
collection.add(HandleHelper.handleRow(columnCount, meta, rs, caseInsensitive));
collection.add(ResultSetUtil.toBean(columnCount, meta, rs, caseInsensitive));
}
return collection;
@@ -235,34 +235,55 @@ public class HandleHelper {
/**
* 处理多条数据并返回一个Bean列表
*
* @param <E> 集合元素类型
* @param <T> 集合类型
* @param rs 数据集
* @param collection 数据集
* @param <E> 集合元素类型
* @param <T> 集合类型
* @param rs 数据集
* @param collection 数据集
* @param elementBeanType Bean类型
* @return Entity列表
* @throws SQLException SQL执行异常
* @since 3.1.0
*/
public static <E, T extends Collection<E>> T handleRsToBeanList(final ResultSet rs, final T collection, final Class<E> elementBeanType) throws SQLException {
public static <E, T extends Collection<E>> T toBeanList(final ResultSet rs, final T collection, final Class<E> elementBeanType) throws SQLException {
final ResultSetMetaData meta = rs.getMetaData();
final int columnCount = meta.getColumnCount();
while (rs.next()) {
collection.add(handleRow(columnCount, meta, rs, elementBeanType));
collection.add(toBean(columnCount, meta, rs, elementBeanType));
}
return collection;
}
/**
* 结果集读取为一个Long值一版用于插入时返回主键等<br>
* 当有多个值返回时只取第一个
*
* @param rs 数据集
* @return long值
* @throws SQLException SQL执行异常
*/
public static Long toLong(final ResultSet rs) throws SQLException {
Long generatedKey = null;
if (rs != null && rs.next()) {
try {
generatedKey = rs.getLong(1);
} catch (final DbRuntimeException e) {
// 自增主键不为数字或者为Oracle的rowid跳过
}
}
return generatedKey;
}
// -------------------------------------------------------------------------------------------------------------- Private method start
/**
* 获取字段值<br>
* 针对日期时间等做单独处理判断
*
* @param rs {@link ResultSet}
* @param columnIndex 字段索引
* @param type 字段类型默认Object
* @param rs {@link ResultSet}
* @param columnIndex 字段索引
* @param type 字段类型默认Object
* @param targetColumnType 结果要求的类型需进行二次转换null或者Object不转换
* @return 字段值
* @throws SQLException SQL异常
@@ -270,19 +291,19 @@ public class HandleHelper {
private static Object getColumnValue(final ResultSet rs, final int columnIndex, final int type, final Type targetColumnType) throws SQLException {
Object rawValue = null;
switch (type) {
case Types.TIMESTAMP:
try{
rawValue = rs.getTimestamp(columnIndex);
} catch (final SQLException ignore){
// issue#776@Github
// 当数据库中日期为0000-00-00 00:00:00报错转为null
}
break;
case Types.TIME:
rawValue = rs.getTime(columnIndex);
break;
default:
rawValue = rs.getObject(columnIndex);
case Types.TIMESTAMP:
try {
rawValue = rs.getTimestamp(columnIndex);
} catch (final SQLException ignore) {
// issue#776@Github
// 当数据库中日期为0000-00-00 00:00:00报错转为null
}
break;
case Types.TIME:
rawValue = rs.getTime(columnIndex);
break;
default:
rawValue = rs.getObject(columnIndex);
}
if (null == targetColumnType || Object.class == targetColumnType) {
// 无需转换

View File

@@ -25,7 +25,7 @@ public class ValueListHandler implements RsHandler<List<List<Object>>>{
public List<List<Object>> handle(final ResultSet rs) throws SQLException {
final ArrayList<List<Object>> result = new ArrayList<>();
while (rs.next()) {
result.add(HandleHelper.handleRowToList(rs));
result.add(ResultSetUtil.handleRowToList(rs));
}
return result;
}

View File

@@ -2,6 +2,7 @@ package cn.hutool.db.sql;
import cn.hutool.core.collection.iter.ArrayIter;
import cn.hutool.core.lang.func.Func1;
import cn.hutool.db.DbRuntimeException;
import cn.hutool.db.DbUtil;
import cn.hutool.db.StatementUtil;
import cn.hutool.db.handler.RsHandler;
@@ -19,7 +20,6 @@ import java.util.Map;
* 此方法为JDBC的简单封装与数据库类型无关
*
* @author loolly
*
*/
public class SqlExecutor {
@@ -28,14 +28,14 @@ public class SqlExecutor {
* 语句包括 插入、更新、删除<br>
* 此方法不会关闭Connection
*
* @param conn 数据库连接对象
* @param sql SQL使用name做为占位符例如:name
* @param conn 数据库连接对象
* @param sql SQL使用name做为占位符例如:name
* @param paramMap 参数Map
* @return 影响的行数
* @throws SQLException SQL执行异常
* @throws DbRuntimeException SQL执行异常
* @since 4.0.10
*/
public static int execute(final Connection conn, final String sql, final Map<String, Object> paramMap) throws SQLException {
public static int execute(final Connection conn, final String sql, final Map<String, Object> paramMap) throws DbRuntimeException {
final NamedSql namedSql = new NamedSql(sql, paramMap);
return execute(conn, namedSql.getSql(), namedSql.getParams());
}
@@ -45,17 +45,19 @@ public class SqlExecutor {
* 语句包括 插入、更新、删除<br>
* 此方法不会关闭Connection
*
* @param conn 数据库连接对象
* @param sql SQL
* @param conn 数据库连接对象
* @param sql SQL
* @param params 参数
* @return 影响的行数
* @throws SQLException SQL执行异常
* @throws DbRuntimeException SQL执行异常
*/
public static int execute(final Connection conn, final String sql, final Object... params) throws SQLException {
public static int execute(final Connection conn, final String sql, final Object... params) throws DbRuntimeException {
PreparedStatement ps = null;
try {
ps = StatementUtil.prepareStatement(conn, sql, params);
return ps.executeUpdate();
} catch (final SQLException e) {
throw new DbRuntimeException(e);
} finally {
DbUtil.close(ps);
}
@@ -65,17 +67,19 @@ public class SqlExecutor {
* 执行调用存储过程<br>
* 此方法不会关闭Connection
*
* @param conn 数据库连接对象
* @param sql SQL
* @param conn 数据库连接对象
* @param sql SQL
* @param params 参数
* @return 如果执行后第一个结果是ResultSet则返回true否则返回false。
* @throws SQLException SQL执行异常
* @throws DbRuntimeException SQL执行异常
*/
public static boolean call(final Connection conn, final String sql, final Object... params) throws SQLException {
public static boolean call(final Connection conn, final String sql, final Object... params) throws DbRuntimeException {
CallableStatement call = null;
try {
call = StatementUtil.prepareCall(conn, sql, params);
return call.execute();
} catch (final SQLException e) {
throw new DbRuntimeException(e);
} finally {
DbUtil.close(call);
}
@@ -85,15 +89,19 @@ public class SqlExecutor {
* 执行调用存储过程<br>
* 此方法不会关闭Connection
*
* @param conn 数据库连接对象
* @param sql SQL
* @param conn 数据库连接对象
* @param sql SQL
* @param params 参数
* @return ResultSet
* @throws SQLException SQL执行异常
* @throws DbRuntimeException SQL执行异常
* @since 4.1.4
*/
public static ResultSet callQuery(final Connection conn, final String sql, final Object... params) throws SQLException {
return StatementUtil.prepareCall(conn, sql, params).executeQuery();
public static ResultSet callQuery(final Connection conn, final String sql, final Object... params) throws DbRuntimeException {
try {
return StatementUtil.prepareCall(conn, sql, params).executeQuery();
} catch (final SQLException e) {
throw new DbRuntimeException(e);
}
}
/**
@@ -101,14 +109,14 @@ public class SqlExecutor {
* 发查询语句包括 插入、更新、删除<br>
* 此方法不会关闭Connection
*
* @param conn 数据库连接对象
* @param sql SQL
* @param conn 数据库连接对象
* @param sql SQL
* @param paramMap 参数Map
* @return 主键
* @throws SQLException SQL执行异常
* @throws DbRuntimeException SQL执行异常
* @since 4.0.10
*/
public static Long executeForGeneratedKey(final Connection conn, final String sql, final Map<String, Object> paramMap) throws SQLException {
public static Long executeForGeneratedKey(final Connection conn, final String sql, final Map<String, Object> paramMap) throws DbRuntimeException {
final NamedSql namedSql = new NamedSql(sql, paramMap);
return executeForGeneratedKey(conn, namedSql.getSql(), namedSql.getParams());
}
@@ -118,13 +126,13 @@ public class SqlExecutor {
* 发查询语句包括 插入、更新、删除<br>
* 此方法不会关闭Connection
*
* @param conn 数据库连接对象
* @param sql SQL
* @param conn 数据库连接对象
* @param sql SQL
* @param params 参数
* @return 主键
* @throws SQLException SQL执行异常
* @throws DbRuntimeException SQL执行异常
*/
public static Long executeForGeneratedKey(final Connection conn, final String sql, final Object... params) throws SQLException {
public static Long executeForGeneratedKey(final Connection conn, final String sql, final Object... params) throws DbRuntimeException {
PreparedStatement ps = null;
ResultSet rs = null;
try {
@@ -139,6 +147,8 @@ public class SqlExecutor {
}
}
return null;
} catch (final SQLException e) {
throw new DbRuntimeException(e);
} finally {
DbUtil.close(ps);
DbUtil.close(rs);
@@ -150,17 +160,19 @@ public class SqlExecutor {
* 语句包括 插入、更新、删除<br>
* 此方法不会关闭Connection
*
* @param conn 数据库连接对象
* @param sql SQL
* @param conn 数据库连接对象
* @param sql SQL
* @param paramsBatch 批量的参数
* @return 每个SQL执行影响的行数
* @throws SQLException SQL执行异常
* @throws DbRuntimeException SQL执行异常
*/
public static int[] executeBatch(final Connection conn, final String sql, final Iterable<Object[]> paramsBatch) throws SQLException {
public static int[] executeBatch(final Connection conn, final String sql, final Iterable<Object[]> paramsBatch) throws DbRuntimeException {
PreparedStatement ps = null;
try {
ps = StatementUtil.prepareStatementForBatch(conn, sql, paramsBatch);
return ps.executeBatch();
} catch (final SQLException e) {
throw new DbRuntimeException(e);
} finally {
DbUtil.close(ps);
}
@@ -174,10 +186,10 @@ public class SqlExecutor {
* @param conn 数据库连接对象
* @param sqls SQL列表
* @return 每个SQL执行影响的行数
* @throws SQLException SQL执行异常
* @throws DbRuntimeException SQL执行异常
* @since 4.5.6
*/
public static int[] executeBatch(final Connection conn, final String... sqls) throws SQLException {
public static int[] executeBatch(final Connection conn, final String... sqls) throws DbRuntimeException {
return executeBatch(conn, new ArrayIter<>(sqls));
}
@@ -189,10 +201,10 @@ public class SqlExecutor {
* @param conn 数据库连接对象
* @param sqls SQL列表
* @return 每个SQL执行影响的行数
* @throws SQLException SQL执行异常
* @throws DbRuntimeException SQL执行异常
* @since 4.5.6
*/
public static int[] executeBatch(final Connection conn, final Iterable<String> sqls) throws SQLException {
public static int[] executeBatch(final Connection conn, final Iterable<String> sqls) throws DbRuntimeException {
Statement statement = null;
try {
statement = conn.createStatement();
@@ -200,6 +212,8 @@ public class SqlExecutor {
statement.addBatch(sql);
}
return statement.executeBatch();
} catch (final SQLException e) {
throw new DbRuntimeException(e);
} finally {
DbUtil.close(statement);
}
@@ -209,16 +223,16 @@ public class SqlExecutor {
* 执行查询语句例如select * from table where field1=:name1 <br>
* 此方法不会关闭Connection
*
* @param <T> 处理结果类型
* @param conn 数据库连接对象
* @param sql 查询语句,使用参数名占位符,例如:name
* @param rsh 结果集处理对象
* @param <T> 处理结果类型
* @param conn 数据库连接对象
* @param sql 查询语句,使用参数名占位符,例如:name
* @param rsh 结果集处理对象
* @param paramMap 参数对
* @return 结果对象
* @throws SQLException SQL执行异常
* @throws DbRuntimeException SQL执行异常
* @since 4.0.10
*/
public static <T> T query(final Connection conn, final String sql, final RsHandler<T> rsh, final Map<String, Object> paramMap) throws SQLException {
public static <T> T query(final Connection conn, final String sql, final RsHandler<T> rsh, final Map<String, Object> paramMap) throws DbRuntimeException {
final NamedSql namedSql = new NamedSql(sql, paramMap);
return query(conn, namedSql.getSql(), rsh, namedSql.getParams());
}
@@ -227,15 +241,15 @@ public class SqlExecutor {
* 执行查询语句<br>
* 此方法不会关闭Connection
*
* @param <T> 处理结果类型
* @param conn 数据库连接对象
* @param <T> 处理结果类型
* @param conn 数据库连接对象
* @param sqlBuilder SQL构建器包含参数
* @param rsh 结果集处理对象
* @param rsh 结果集处理对象
* @return 结果对象
* @throws SQLException SQL执行异常
* @throws DbRuntimeException SQL执行异常
* @since 5.5.3
*/
public static <T> T query(final Connection conn, final SqlBuilder sqlBuilder, final RsHandler<T> rsh) throws SQLException {
public static <T> T query(final Connection conn, final SqlBuilder sqlBuilder, final RsHandler<T> rsh) throws DbRuntimeException {
return query(conn, sqlBuilder.build(), rsh, sqlBuilder.getParamValueArray());
}
@@ -243,19 +257,21 @@ public class SqlExecutor {
* 执行查询语句<br>
* 此方法不会关闭Connection
*
* @param <T> 处理结果类型
* @param conn 数据库连接对象
* @param sql 查询语句
* @param rsh 结果集处理对象
* @param <T> 处理结果类型
* @param conn 数据库连接对象
* @param sql 查询语句
* @param rsh 结果集处理对象
* @param params 参数
* @return 结果对象
* @throws SQLException SQL执行异常
* @throws DbRuntimeException SQL执行异常
*/
public static <T> T query(final Connection conn, final String sql, final RsHandler<T> rsh, final Object... params) throws SQLException {
public static <T> T query(final Connection conn, final String sql, final RsHandler<T> rsh, final Object... params) throws DbRuntimeException {
PreparedStatement ps = null;
try {
ps = StatementUtil.prepareStatement(conn, sql, params);
return executeQuery(ps, rsh);
} catch (final SQLException e) {
throw new DbRuntimeException(e);
} finally {
DbUtil.close(ps);
}
@@ -265,30 +281,26 @@ public class SqlExecutor {
* 执行自定义的{@link PreparedStatement},结果使用{@link RsHandler}处理<br>
* 此方法主要用于自定义场景,如游标查询等
*
* @param <T> 处理结果类型
* @param conn 数据库连接对象
* @param <T> 处理结果类型
* @param conn 数据库连接对象
* @param statementFunc 自定义{@link PreparedStatement}创建函数
* @param rsh 自定义结果集处理
* @param rsh 自定义结果集处理
* @return 结果
* @throws SQLException SQL执行异常
* @throws DbRuntimeException SQL执行异常
* @since 5.7.17
*/
public static <T> T query(final Connection conn, final Func1<Connection, PreparedStatement> statementFunc, final RsHandler<T> rsh) throws SQLException {
public static <T> T query(final Connection conn, final Func1<Connection, PreparedStatement> statementFunc, final RsHandler<T> rsh) throws DbRuntimeException {
PreparedStatement ps = null;
try {
ps = statementFunc.call(conn);
ps = statementFunc.callWithRuntimeException(conn);
return executeQuery(ps, rsh);
} catch (final Exception e) {
if(e instanceof SQLException){
throw (SQLException) e;
}
throw new RuntimeException(e);
} finally {
DbUtil.close(ps);
}
}
// -------------------------------------------------------------------------------------- Execute With PreparedStatement
/**
* 用于执行 INSERT、UPDATE 或 DELETE 语句以及 SQL DDL数据定义语言语句例如 CREATE TABLE 和 DROP TABLE。<br>
* INSERT、UPDATE 或 DELETE 语句的效果是修改表中零行或多行中的一列或多列。<br>
@@ -296,14 +308,18 @@ public class SqlExecutor {
* 对于 CREATE TABLE 或 DROP TABLE 等不操作行的语句executeUpdate 的返回值总为零。<br>
* 此方法不会关闭PreparedStatement
*
* @param ps PreparedStatement对象
* @param ps PreparedStatement对象
* @param params 参数
* @return 影响的行数
* @throws SQLException SQL执行异常
* @throws DbRuntimeException SQL执行异常
*/
public static int executeUpdate(final PreparedStatement ps, final Object... params) throws SQLException {
StatementUtil.fillParams(ps, params);
return ps.executeUpdate();
public static int executeUpdate(final PreparedStatement ps, final Object... params) throws DbRuntimeException {
try {
StatementUtil.fillParams(ps, params);
return ps.executeUpdate();
} catch (final SQLException e) {
throw new DbRuntimeException(e);
}
}
/**
@@ -311,43 +327,51 @@ public class SqlExecutor {
* 如果执行后第一个结果是ResultSet则返回true否则返回false。<br>
* 此方法不会关闭PreparedStatement
*
* @param ps PreparedStatement对象
* @param ps PreparedStatement对象
* @param params 参数
* @return 如果执行后第一个结果是ResultSet则返回true否则返回false。
* @throws SQLException SQL执行异常
* @throws DbRuntimeException SQL执行异常
*/
public static boolean execute(final PreparedStatement ps, final Object... params) throws SQLException {
StatementUtil.fillParams(ps, params);
return ps.execute();
public static boolean execute(final PreparedStatement ps, final Object... params) throws DbRuntimeException {
try {
StatementUtil.fillParams(ps, params);
return ps.execute();
} catch (final SQLException e) {
throw new DbRuntimeException(e);
}
}
/**
* 执行查询语句<br>
* 此方法不会关闭PreparedStatement
*
* @param <T> 处理结果类型
* @param ps PreparedStatement
* @param rsh 结果集处理对象
* @param <T> 处理结果类型
* @param ps PreparedStatement
* @param rsh 结果集处理对象
* @param params 参数
* @return 结果对象
* @throws SQLException SQL执行异常
* @throws DbRuntimeException SQL执行异常
*/
public static <T> T query(final PreparedStatement ps, final RsHandler<T> rsh, final Object... params) throws SQLException {
StatementUtil.fillParams(ps, params);
return executeQuery(ps, rsh);
public static <T> T query(final PreparedStatement ps, final RsHandler<T> rsh, final Object... params) throws DbRuntimeException {
try {
StatementUtil.fillParams(ps, params);
return executeQuery(ps, rsh);
} catch (final SQLException e) {
throw new DbRuntimeException(e);
}
}
/**
* 执行查询语句并关闭PreparedStatement
*
* @param <T> 处理结果类型
* @param ps PreparedStatement
* @param rsh 结果集处理对象
* @param <T> 处理结果类型
* @param ps PreparedStatement
* @param rsh 结果集处理对象
* @param params 参数
* @return 结果对象
* @throws SQLException SQL执行异常
* @throws DbRuntimeException SQL执行异常
*/
public static <T> T queryAndClosePs(final PreparedStatement ps, final RsHandler<T> rsh, final Object... params) throws SQLException {
public static <T> T queryAndClosePs(final PreparedStatement ps, final RsHandler<T> rsh, final Object... params) throws DbRuntimeException {
try {
return query(ps, rsh, params);
} finally {
@@ -356,20 +380,23 @@ public class SqlExecutor {
}
// -------------------------------------------------------------------------------------------------------------------------------- Private method start
/**
* 执行查询
*
* @param ps {@link PreparedStatement}
* @param ps {@link PreparedStatement}
* @param rsh 结果集处理对象
* @return 结果对象
* @throws SQLException SQL执行异常
* @throws DbRuntimeException SQL执行异常
* @since 4.1.13
*/
private static <T> T executeQuery(final PreparedStatement ps, final RsHandler<T> rsh) throws SQLException {
private static <T> T executeQuery(final PreparedStatement ps, final RsHandler<T> rsh) throws DbRuntimeException {
ResultSet rs = null;
try {
rs = ps.executeQuery();
return rsh.handle(rs);
} catch (final SQLException e) {
throw new DbRuntimeException(e);
} finally {
DbUtil.close(rs);
}