Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.xiaoleilu.hutool.db.SqlConnRunner Maven / Gradle / Ivy
package com.xiaoleilu.hutool.db;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.Collection;
import java.util.List;
import javax.sql.DataSource;
import com.xiaoleilu.hutool.collection.CollectionUtil;
import com.xiaoleilu.hutool.db.dialect.Dialect;
import com.xiaoleilu.hutool.db.dialect.DialectFactory;
import com.xiaoleilu.hutool.db.handler.EntityListHandler;
import com.xiaoleilu.hutool.db.handler.NumberHandler;
import com.xiaoleilu.hutool.db.handler.PageResultHandler;
import com.xiaoleilu.hutool.db.handler.RsHandler;
import com.xiaoleilu.hutool.db.sql.Condition.LikeType;
import com.xiaoleilu.hutool.db.sql.Query;
import com.xiaoleilu.hutool.db.sql.SqlExecutor;
import com.xiaoleilu.hutool.lang.Assert;
import com.xiaoleilu.hutool.log.StaticLog;
import com.xiaoleilu.hutool.util.ArrayUtil;
import com.xiaoleilu.hutool.util.StrUtil;
/**
* SQL执行类
* 此执行类只接受方言参数,不需要数据源,只有在执行方法时需要数据库连接对象
* 此对象存在的意义在于,可以由使用者自定义数据库连接对象,并执行多个方法,方便事务的统一控制或减少连接对象的创建关闭
* @author Luxiaolei
*
*/
public class SqlConnRunner{
private Dialect dialect;
/**
* 实例化一个新的SQL运行对象
*
* @param dialect 方言
* @return SQL执行类
*/
public static SqlConnRunner create(Dialect dialect) {
return new SqlConnRunner(dialect);
}
/**
* 实例化一个新的SQL运行对象
*
* @param ds 数据源
* @return SQL执行类
*/
public static SqlConnRunner create(DataSource ds) {
return new SqlConnRunner(DialectFactory.newDialect(ds));
}
/**
* 实例化一个新的SQL运行对象
*
* @param driverClassName 驱动类名
* @return SQL执行类
*/
public static SqlConnRunner create(String driverClassName) {
return new SqlConnRunner(driverClassName);
}
//------------------------------------------------------- Constructor start
/**
* 构造
* @param dialect 方言
*/
public SqlConnRunner(Dialect dialect) {
StaticLog.debug("Use Dialect: [{}].", dialect.getClass().getSimpleName());
this.dialect = dialect;
}
/**
* 构造
* @param driverClassName 驱动类名,,用于识别方言
*/
public SqlConnRunner(String driverClassName) {
this(DialectFactory.newDialect(driverClassName));
}
//------------------------------------------------------- Constructor end
//---------------------------------------------------------------------------- CRUD start
/**
* 插入数据
* 此方法不会关闭Connection
* @param conn 数据库连接
* @param record 记录
* @return 插入行数
* @throws SQLException SQL执行异常
*/
public int insert(Connection conn, Entity record) throws SQLException {
checkConn(conn);
if(CollectionUtil.isEmpty(record)){
throw new SQLException("Empty entity provided!");
}
PreparedStatement ps = null;
try {
ps = dialect.psForInsert(conn, record);
return ps.executeUpdate();
} catch (SQLException e) {
throw e;
} finally {
DbUtil.close(ps);
}
}
/**
* 批量插入数据
* 需要注意的是,批量插入每一条数据结构必须一致。批量插入数据时会获取第一条数据的字段结构,之后的数据会按照这个格式插入。
* 也就是说假如第一条数据只有2个字段,后边数据多于这两个字段的部分将被抛弃。
* 此方法不会关闭Connection
*
* @param conn 数据库连接
* @param records 记录列表,记录KV必须严格一致
* @return 插入行数
* @throws SQLException SQL执行异常
*/
public int[] insert(Connection conn, Collection records) throws SQLException {
return insert(conn, records.toArray(new Entity[records.size()]));
}
/**
* 批量插入数据
* 批量插入必须严格保持Entity的结构一致,不一致会导致插入数据出现不可预知的结果
* 此方法不会关闭Connection
*
* @param conn 数据库连接
* @param records 记录列表,记录KV必须严格一致
* @return 插入行数
* @throws SQLException SQL执行异常
*/
public int[] insert(Connection conn, Entity... records) throws SQLException {
checkConn(conn);
if(ArrayUtil.isEmpty(records)){
return new int[]{0};
}
//单条单独处理
if(1 == records.length) {
return new int[] { insert(conn, records[0])};
}
PreparedStatement ps = null;
try {
ps = dialect.psForInsertBatch(conn, records);
return ps.executeBatch();
} finally {
DbUtil.close(ps);
}
}
/**
* 插入数据
* 此方法不会关闭Connection
* @param conn 数据库连接
* @param record 记录
* @return 主键列表
* @throws SQLException SQL执行异常
*/
public List insertForGeneratedKeys(Connection conn, Entity record) throws SQLException {
checkConn(conn);
if(CollectionUtil.isEmpty(record)){
throw new SQLException("Empty entity provided!");
}
PreparedStatement ps = null;
try {
ps = dialect.psForInsert(conn, record);
ps.executeUpdate();
return DbUtil.getGeneratedKeys(ps);
} catch (SQLException e) {
throw e;
} finally {
DbUtil.close(ps);
}
}
/**
* 插入数据
* 此方法不会关闭Connection
* @param conn 数据库连接
* @param record 记录
* @return 自增主键
* @throws SQLException SQL执行异常
*/
public Long insertForGeneratedKey(Connection conn, Entity record) throws SQLException {
checkConn(conn);
if(CollectionUtil.isEmpty(record)){
throw new SQLException("Empty entity provided!");
}
PreparedStatement ps = null;
try {
ps = dialect.psForInsert(conn, record);
ps.executeUpdate();
return DbUtil.getGeneratedKeyOfLong(ps);
} catch (SQLException e) {
throw e;
} finally {
DbUtil.close(ps);
}
}
/**
* 删除数据
* 此方法不会关闭Connection
* @param conn 数据库连接
* @param where 条件
* @return 影响行数
* @throws SQLException SQL执行异常
*/
public int del(Connection conn, Entity where) throws SQLException {
checkConn(conn);
if(CollectionUtil.isEmpty(where)){
//不允许做全表删除
throw new SQLException("Empty entity provided!");
}
final Query query = new Query(DbUtil.buildConditions(where), where.getTableName());
PreparedStatement ps = null;
try {
ps = dialect.psForDelete(conn, query);
return ps.executeUpdate();
} catch (SQLException e) {
throw e;
} finally {
DbUtil.close(ps);
}
}
/**
* 更新数据
* 此方法不会关闭Connection
* @param conn 数据库连接
* @param record 记录
* @param where 条件
* @return 影响行数
* @throws SQLException SQL执行异常
*/
public int update(Connection conn, Entity record, Entity where) throws SQLException {
checkConn(conn);
if(CollectionUtil.isEmpty(record)){
throw new SQLException("Empty entity provided!");
}
if(CollectionUtil.isEmpty(where)){
//不允许做全表更新
throw new SQLException("Empty where provided!");
}
//表名可以从被更新记录的Entity中获得,也可以从Where中获得
String tableName = record.getTableName();
if(StrUtil.isBlank(tableName)){
tableName = where.getTableName();
record.setTableName(tableName);
}
final Query query = new Query(DbUtil.buildConditions(where), tableName);
PreparedStatement ps = null;
try {
ps = dialect.psForUpdate(conn, record, query);
return ps.executeUpdate();
} catch (SQLException e) {
throw e;
} finally {
DbUtil.close(ps);
}
}
/**
* 查询
* 此方法不会关闭Connection
*
* @param 结果对象类型
* @param conn 数据库连接对象
* @param query {@link Query}
* @param rsh 结果集处理对象
* @return 结果对象
* @throws SQLException SQL执行异常
*/
public T find(Connection conn, Query query, RsHandler rsh) throws SQLException {
checkConn(conn);
Assert.notNull(query, "[query] is null !");
PreparedStatement ps = null;
try {
ps = dialect.psForFind(conn, query);
return SqlExecutor.query(ps, rsh);
} catch (SQLException e) {
throw e;
} finally {
DbUtil.close(ps);
}
}
/**
* 查询
* 此方法不会关闭Connection
*
* @param 结果对象类型
* @param conn 数据库连接对象
* @param fields 返回的字段列表,null则返回所有字段
* @param where 条件实体类(包含表名)
* @param rsh 结果集处理对象
* @return 结果对象
* @throws SQLException SQL执行异常
*/
public T find(Connection conn, Collection fields, Entity where, RsHandler rsh) throws SQLException {
checkConn(conn);
final Query query = new Query(DbUtil.buildConditions(where), where.getTableName());
query.setFields(fields);
return find(conn, query, rsh);
}
/**
* 查询,返回指定字段列表
* 此方法不会关闭Connection
*
* @param 结果对象类型
* @param conn 数据库连接对象
* @param where 条件实体类(包含表名)
* @param rsh 结果集处理对象
* @param fields 字段列表,可变长参数如果无值表示查询全部字段
* @return 结果对象
* @throws SQLException SQL执行异常
*/
public T find(Connection conn, Entity where, RsHandler rsh, String... fields) throws SQLException {
return find(conn, CollectionUtil.newArrayList(fields), where, rsh);
}
/**
* 查询数据列表,返回字段在where参数中定义
*
* @param conn 数据库连接对象
* @param where 条件实体类(包含表名)
* @return 数据对象列表
* @throws SQLException SQL执行异常
* @since 3.2.1
*/
public List find(Connection conn, Entity where) throws SQLException{
return find(conn, where.getFieldNames(), where, EntityListHandler.create());
}
/**
* 查询数据列表,返回所有字段
*
* @param conn 数据库连接对象
* @param where 条件实体类(包含表名)
* @return 数据对象列表
* @throws SQLException SQL执行异常
*/
public List findAll(Connection conn, Entity where) throws SQLException{
return find(conn, where, EntityListHandler.create());
}
/**
* 查询数据列表,返回所有字段
*
* @param conn 数据库连接对象
* @param tableName 表名
* @return 数据对象列表
* @throws SQLException SQL执行异常
*/
public List findAll(Connection conn, String tableName) throws SQLException{
return findAll(conn, Entity.create(tableName));
}
/**
* 根据某个字段名条件查询数据列表,返回所有字段
*
* @param conn 数据库连接对象
* @param tableName 表名
* @param field 字段名
* @param value 字段值
* @return 数据对象列表
* @throws SQLException SQL执行异常
*/
public List findBy(Connection conn, String tableName, String field, 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 findLike(Connection conn, String tableName, String field, String value, LikeType likeType) throws SQLException{
return findAll(conn, Entity.create(tableName).set(field, DbUtil.buildLikeValue(value, likeType)));
}
/**
* 根据某个字段名条件查询数据列表,返回所有字段
*
* @param conn 数据库连接对象
* @param tableName 表名
* @param field 字段名
* @param values 字段值列表
* @return 数据对象列表
* @throws SQLException SQL执行异常
*/
public List findIn(Connection conn, String tableName, String field, Object... values) throws SQLException{
return findAll(conn, Entity.create(tableName).set(field, values));
}
/**
* 结果的条目数
* @param conn 数据库连接对象
* @param where 查询条件
* @return 复合条件的结果数
* @throws SQLException SQL执行异常
*/
public int count(Connection conn, Entity where) throws SQLException {
checkConn(conn);
final Query query = new Query(DbUtil.buildConditions(where), where.getTableName());
PreparedStatement ps = null;
try {
ps = dialect.psForCount(conn, query);
return SqlExecutor.query(ps, new NumberHandler()).intValue();
} catch (SQLException e) {
throw e;
} finally {
DbUtil.close(ps);
}
}
/**
* 分页查询
* 此方法不会关闭Connection
*
* @param 结果对象类型
* @param conn 数据库连接对象
* @param fields 返回的字段列表,null则返回所有字段
* @param where 条件实体类(包含表名)
* @param pageNumber 页码
* @param numPerPage 每页条目数
* @param rsh 结果集处理对象
* @return 结果对象
* @throws SQLException SQL执行异常
*/
public T page(Connection conn, Collection fields, Entity where, int pageNumber, int numPerPage, RsHandler rsh) throws SQLException {
return page(conn, fields, where, new Page(pageNumber, numPerPage), rsh);
}
/**
* 分页查询
* 此方法不会关闭Connection
*
* @param 结果对象类型
* @param conn 数据库连接对象
* @param fields 返回的字段列表,null则返回所有字段
* @param where 条件实体类(包含表名)
* @param page 分页对象
* @param rsh 结果集处理对象
* @return 结果对象
* @throws SQLException SQL执行异常
*/
public T page(Connection conn, Collection fields, Entity where, Page page, RsHandler rsh) throws SQLException {
checkConn(conn);
if(null == page){
return this.find(conn, fields, where, rsh);
}
final Query query = new Query(DbUtil.buildConditions(where), where.getTableName());
query.setFields(fields);
query.setPage(page);
return SqlExecutor.queryAndClosePs(dialect.psForPage(conn, query), rsh);
}
/**
* 分页查询
* 此方法不会关闭Connection
*
* @param conn 数据库连接对象
* @param fields 返回的字段列表,null则返回所有字段
* @param where 条件实体类(包含表名)
* @param page 页码
* @param numPerPage 每页条目数
* @return 结果对象
* @throws SQLException SQL执行异常
*/
public PageResult page(Connection conn, Collection fields, Entity where, int page, int numPerPage) throws SQLException {
checkConn(conn);
final int count = count(conn, where);
PageResultHandler pageResultHandler = PageResultHandler.create(new PageResult(page, numPerPage, count));
return this.page(conn, fields, where, page, numPerPage, pageResultHandler);
}
/**
* 分页查询
* 此方法不会关闭Connection
*
* @param conn 数据库连接对象
* @param fields 返回的字段列表,null则返回所有字段
* @param where 条件实体类(包含表名)
* @param page 分页对象
* @return 结果对象
* @throws SQLException SQL执行异常
*/
public PageResult page(Connection conn, Collection fields, Entity where, Page page) throws SQLException {
checkConn(conn);
//查询全部
if(null == page){
List entityList = this.find(conn, fields, where, new EntityListHandler());
final PageResult pageResult = new PageResult(0, entityList.size(), entityList.size());
pageResult.addAll(entityList);
return pageResult;
}
final int count = count(conn, where);
PageResultHandler pageResultHandler = PageResultHandler.create(new PageResult(page.getPageNumber(), page.getPageSize(), count));
return this.page(conn, fields, where, page, pageResultHandler);
}
/**
* 分页全字段查询
* 此方法不会关闭Connection
*
* @param conn 数据库连接对象
* @param where 条件实体类(包含表名)
* @param page 分页对象
* @return 结果对象
* @throws SQLException SQL执行异常
*/
public PageResult page(Connection conn, Entity where, Page page) throws SQLException {
return this.page(conn, null, where, page);
}
//---------------------------------------------------------------------------- CRUD end
//---------------------------------------------------------------------------- Getters and Setters end
/**
* @return SQL方言
*/
public Dialect getDialect() {
return dialect;
}
/**
* 设置SQL方言
* @param dialect 方言
*/
public void setDialect(Dialect dialect) {
this.dialect = dialect;
}
//---------------------------------------------------------------------------- Getters and Setters end
//---------------------------------------------------------------------------- Private method start
private void checkConn(Connection conn){
if(null == conn){
throw new NullPointerException("Connection object is null!");
}
}
//---------------------------------------------------------------------------- Private method start
}