com.xiaoleilu.hutool.db.Session Maven / Gradle / Ivy
package com.xiaoleilu.hutool.db;
import java.io.Closeable;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Savepoint;
import javax.sql.DataSource;
import com.xiaoleilu.hutool.db.dialect.DialectFactory;
import com.xiaoleilu.hutool.db.ds.DSFactory;
import com.xiaoleilu.hutool.lang.VoidFunc;
import com.xiaoleilu.hutool.log.Log;
import com.xiaoleilu.hutool.log.LogFactory;
import com.xiaoleilu.hutool.util.StrUtil;
/**
* 数据库SQL执行会话
* 会话通过共用Connection而可以实现JDBC事务
* 一个会话只维护一个连接,推荐在执行完后关闭Session,避免重用
* 本对象并不是线程安全的,多个线程共用一个Session将会导致不可预知的问题
*
* @author loolly
*
*/
public class Session extends AbstractSqlRunner implements Closeable {
private final static Log log = LogFactory.get();
private Connection conn = null;
private Boolean isSupportTransaction = null;
/**
* 创建默认数据源会话
*
* @return {@link Session}
* @since 3.2.3
*/
public static Session create() {
return new Session(DSFactory.get());
}
/**
* 创建会话
*
* @param ds 数据源
* @return {@link Session}
*/
public static Session create(DataSource ds) {
return new Session(ds);
}
/**
* 创建会话
*
* @param conn 数据库连接对象
* @return {@link Session}
*/
public static Session create(Connection conn) {
return new Session(conn);
}
// ---------------------------------------------------------------------------- Constructor start
/**
* 构造
*
* @param ds 数据源
*/
public Session(DataSource ds) {
try {
this.conn = ds.getConnection();
} catch (SQLException e) {
throw new DbRuntimeException("Get connection error!", e);
}
this.runner = new SqlConnRunner(DialectFactory.newDialect(conn));
}
/**
* 构造
*
* @param conn 数据库连接对象
*/
public Session(Connection conn) {
this.conn = conn;
this.runner = new SqlConnRunner(DialectFactory.newDialect(conn));
}
// ---------------------------------------------------------------------------- Constructor end
// ---------------------------------------------------------------------------- Getters and Setters end
/**
* 获得{@link Connection}
*
* @return {@link Connection}
*/
public Connection getConn() {
return conn;
}
/**
* 设置{@link Connection}
*
* @param conn {@link Connection}
*/
public void setConn(Connection conn) {
this.conn = conn;
}
/**
* 获得{@link SqlConnRunner}
*
* @return {@link SqlConnRunner}
*/
public SqlConnRunner getRunner() {
return runner;
}
/**
* 设置{@link SqlConnRunner}
*
* @param runner {@link SqlConnRunner}
*/
public void setRunner(SqlConnRunner runner) {
this.runner = runner;
}
// ---------------------------------------------------------------------------- Getters and Setters end
// ---------------------------------------------------------------------------- Transaction method start
/**
* 数据库是否支持事务
*
* @return 是否支持事务
* @throws DbRuntimeException SQLException包装
* @since 3.2.3
*/
public boolean isSupportTransaction() throws DbRuntimeException{
if (null == isSupportTransaction) {
try {
isSupportTransaction = conn.getMetaData().supportsTransactions();
} catch (SQLException e) {
throw new DbRuntimeException(e, "Because of SQLException [{}], We can not know transation support or not.", e.getMessage());
}
}
return this.isSupportTransaction;
}
/**
* 开始事务
*
* @throws SQLException SQL执行异常
*/
public void beginTransaction() throws SQLException {
if (null == isSupportTransaction) {
isSupportTransaction = conn.getMetaData().supportsTransactions();
}
if (false == isSupportTransaction) {
throw new SQLException("Transaction not supported for current database!");
}
conn.setAutoCommit(false);
}
/**
* 提交事务
*
* @throws SQLException SQL执行异常
*/
public void commit() throws SQLException {
try {
conn.commit();
} catch (SQLException e) {
throw e;
} finally {
try {
conn.setAutoCommit(true); // 事务结束,恢复自动提交
} catch (SQLException e) {
log.error(e);
}
}
}
/**
* 回滚事务
*
* @throws SQLException SQL执行异常
*/
public void rollback() throws SQLException {
try {
conn.rollback();
} catch (SQLException e) {
throw e;
} finally {
try {
conn.setAutoCommit(true); // 事务结束,恢复自动提交
} catch (SQLException e) {
log.error(e);
}
}
}
/**
* 静默回滚事务
* 回滚事务
*/
public void quietRollback() {
try {
conn.rollback();
} catch (Exception e) {
log.error(e);
} finally {
try {
conn.setAutoCommit(true); // 事务结束,恢复自动提交
} catch (SQLException e) {
log.error(e);
}
}
}
/**
* 回滚到某个保存点,保存点的设置请使用setSavepoint方法
*
* @param savepoint 保存点
* @throws SQLException SQL执行异常
*/
public void rollback(Savepoint savepoint) throws SQLException {
try {
conn.rollback(savepoint);
} catch (SQLException e) {
throw e;
} finally {
try {
conn.setAutoCommit(true); // 事务结束,恢复自动提交
} catch (SQLException e) {
log.error(e);
}
}
}
/**
* 静默回滚到某个保存点,保存点的设置请使用setSavepoint方法
*
* @param savepoint 保存点
* @throws SQLException SQL执行异常
*/
public void quietRollback(Savepoint savepoint) throws SQLException {
try {
conn.rollback(savepoint);
} catch (Exception e) {
log.error(e);
} finally {
try {
conn.setAutoCommit(true); // 事务结束,恢复自动提交
} catch (SQLException e) {
log.error(e);
}
}
}
/**
* 设置保存点
*
* @return 保存点对象
* @throws SQLException SQL执行异常
*/
public Savepoint setSavepoint() throws SQLException {
return conn.setSavepoint();
}
/**
* 设置保存点
*
* @param name 保存点的名称
* @return 保存点对象
* @throws SQLException SQL执行异常
*/
public Savepoint setSavepoint(String name) throws SQLException {
return conn.setSavepoint(name);
}
/**
* 设置事务的隔离级别
*
* Connection.TRANSACTION_NONE 驱动不支持事务
* Connection.TRANSACTION_READ_UNCOMMITTED 允许脏读、不可重复读和幻读
* Connection.TRANSACTION_READ_COMMITTED 禁止脏读,但允许不可重复读和幻读
* Connection.TRANSACTION_REPEATABLE_READ 禁止脏读和不可重复读,单运行幻读
* Connection.TRANSACTION_SERIALIZABLE 禁止脏读、不可重复读和幻读
*
* @param level 隔离级别
* @throws SQLException SQL执行异常
*/
public void setTransactionIsolation(int level) throws SQLException {
if (conn.getMetaData().supportsTransactionIsolationLevel(level) == false) {
throw new SQLException(StrUtil.format("Transaction isolation [{}] not support!", level));
}
conn.setTransactionIsolation(level);
}
/**
* 在事务中执行操作,通过实现{@link VoidFunc}接口的call方法执行多条SQL语句从而完成事务
*
* @param func 函数抽象,在函数中执行多个SQL操作,多个操作会被合并为同一事务
* @since 3.2.3
*/
public void trans(VoidFunc func) {
try {
beginTransaction();
func.call();
commit();
} catch (Exception e) {
quietRollback();
throw new DbRuntimeException(e);
}
}
// ---------------------------------------------------------------------------- Transaction method end
/**
* 获得连接,Session中使用同一个连接
*
* @return {@link Connection}
* @throws SQLException SQL执行异常
*/
@Override
public Connection getConnection() throws SQLException {
// Session中使用同一个连接操作
return this.conn;
}
/**
* Session中不关闭连接
*
* @param conn {@link Connection}
*/
@Override
public void closeConnection(Connection conn) {
// Session中不关闭连接
}
@Override
public void close() {
DbUtil.close(conn);
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy