📄 jdbcconnection.java
字号:
/*
* Copyright 2004-2008 H2 Group. Licensed under the H2 License, Version 1.0
* (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.jdbc;
import java.io.InputStream;
import java.io.Reader;
import java.sql.Blob;
import java.sql.CallableStatement;
import java.sql.Clob;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.SQLWarning;
import java.sql.Savepoint;
import java.sql.Statement;
import java.util.Map;
import java.util.Properties;
import org.h2.command.CommandInterface;
import org.h2.constant.ErrorCode;
import org.h2.constant.SysProperties;
import org.h2.engine.ConnectionInfo;
import org.h2.engine.Constants;
import org.h2.engine.SessionInterface;
import org.h2.engine.SessionRemote;
import org.h2.expression.ParameterInterface;
import org.h2.message.Message;
import org.h2.message.Trace;
import org.h2.message.TraceObject;
import org.h2.result.ResultInterface;
import org.h2.util.ClassUtils;
import org.h2.util.JdbcConnectionListener;
import org.h2.value.Value;
import org.h2.value.ValueInt;
import org.h2.value.ValueLob;
import org.h2.value.ValueNull;
import org.h2.value.ValueString;
//#ifdef JDK16
/*
import java.sql.Array;
import java.sql.NClob;
import java.sql.Struct;
import java.sql.SQLXML;
import java.sql.SQLClientInfoException;
*/
//#endif
/**
* Represents a connection (session) to a database.
*/
public class JdbcConnection extends TraceObject implements Connection {
// TODO test: check if enough synchronization on jdbc objects
// TODO feature: auto-reconnect on lost connection
private String url;
private String user;
private int holdability = 1; // ResultSet.HOLD_CURSORS_OVER_COMMIT
private SessionInterface session;
private CommandInterface commit, rollback;
private CommandInterface setAutoCommitTrue, setAutoCommitFalse, getAutoCommit;
private CommandInterface getReadOnly, getGeneratedKeys;
private CommandInterface setLockMode, getLockMode;
private CommandInterface setQueryTimeout, getQueryTimeout;
private Exception openStackTrace;
//#ifdef JDK14
private int savepointId;
//#endif
private Trace trace;
private JdbcConnectionListener listener;
private boolean isInternal;
private String catalog;
private Statement executingStatement;
/**
* Creates a new statement.
*
* @return the new statement
* @throws SQLException if the connection is closed
*/
public Statement createStatement() throws SQLException {
try {
int id = getNextId(TraceObject.STATEMENT);
if (debug()) {
debugCodeAssign("Statement", TraceObject.STATEMENT, id, "createStatement()");
}
checkClosed();
return new JdbcStatement(session, this, ResultSet.TYPE_FORWARD_ONLY, id, false);
} catch (Throwable e) {
throw logAndConvert(e);
}
}
/**
* Creates a statement with the specified result set type and concurrency.
*
* @return the statement
* @throws SQLException
* if the connection is closed or the result set type or
* concurrency are not supported
*/
public Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException {
try {
int id = getNextId(TraceObject.STATEMENT);
if (debug()) {
debugCodeAssign("Statement", TraceObject.STATEMENT, id, "createStatement(" + resultSetType + ", " + resultSetConcurrency + ")");
}
checkClosed();
checkTypeAndConcurrency(resultSetType, resultSetConcurrency);
return new JdbcStatement(session, this, resultSetType, id, false);
} catch (Throwable e) {
throw logAndConvert(e);
}
}
/**
* Creates a statement with the specified result set type, concurrency, and
* holdability.
*
* @return the statement
* @throws SQLException if the connection is closed or the result set type,
* concurrency, or holdability are not supported
*/
public Statement createStatement(int resultSetType, int resultSetConcurrency, int resultSetHoldability)
throws SQLException {
try {
int id = getNextId(TraceObject.STATEMENT);
if (debug()) {
debugCodeAssign("Statement", TraceObject.STATEMENT, id,
"createStatement(" + resultSetType + ", " + resultSetConcurrency + ", " + resultSetHoldability + ")");
}
checkClosed();
checkTypeAndConcurrency(resultSetType, resultSetConcurrency);
checkHoldability(resultSetHoldability);
return new JdbcStatement(session, this, resultSetType, id, false);
} catch (Throwable e) {
throw logAndConvert(e);
}
}
/**
* Creates a new prepared statement.
*
* @return the prepared statement
* @throws SQLException
* if the connection is closed
*/
public PreparedStatement prepareStatement(String sql) throws SQLException {
try {
int id = getNextId(TraceObject.PREPARED_STATEMENT);
if (debug()) {
debugCodeAssign("PreparedStatement", TraceObject.PREPARED_STATEMENT, id, "prepareStatement(" + quote(sql) + ")");
}
checkClosed();
sql = translateSQL(sql);
return new JdbcPreparedStatement(session, this, sql, ResultSet.TYPE_FORWARD_ONLY, id, false);
} catch (Throwable e) {
throw logAndConvert(e);
}
}
PreparedStatement prepareAutoCloseStatement(String sql) throws SQLException {
try {
int id = getNextId(TraceObject.PREPARED_STATEMENT);
if (debug()) {
debugCodeAssign("PreparedStatement", TraceObject.PREPARED_STATEMENT, id, "prepareStatement(" + quote(sql) + ")");
}
checkClosed();
sql = translateSQL(sql);
return new JdbcPreparedStatement(session, this, sql, ResultSet.TYPE_FORWARD_ONLY, id, true);
} catch (Throwable e) {
throw logAndConvert(e);
}
}
/**
* Gets the database meta data for this database.
*
* @return the database meta data
* @throws SQLException
* if the connection is closed
*/
public DatabaseMetaData getMetaData() throws SQLException {
try {
int id = getNextId(TraceObject.DATABASE_META_DATA);
if (debug()) {
debugCodeAssign("DatabaseMetaData", TraceObject.DATABASE_META_DATA, id, "getMetaData()");
}
checkClosed();
return new JdbcDatabaseMetaData(this, trace, id);
} catch (Throwable e) {
throw logAndConvert(e);
}
}
/**
* INTERNAL
*/
public void setJdbcConnectionListener(JdbcConnectionListener listener) {
this.listener = listener;
}
/**
* INTERNAL
*/
public SessionInterface getSession() {
return session;
}
/**
* Closes this connection. All open statements, prepared statements and
* result sets that where created by this connection become invalid after
* calling this method. If there is an uncommitted transaction, it will be
* rolled back.
*/
public void close() throws SQLException {
synchronized (this) {
if (listener == null) {
closeConnection();
} else {
listener.closed(this);
}
}
}
/**
* INTERNAL
*/
public void closeConnection() throws SQLException {
try {
debugCodeCall("close");
if (executingStatement != null) {
executingStatement.cancel();
}
if (session == null) {
return;
}
session.cancel();
synchronized (session) {
try {
if (!session.isClosed()) {
try {
rollbackInternal();
commit = closeAndSetNull(commit);
rollback = closeAndSetNull(rollback);
setAutoCommitTrue = closeAndSetNull(setAutoCommitTrue);
setAutoCommitFalse = closeAndSetNull(setAutoCommitFalse);
getAutoCommit = closeAndSetNull(getAutoCommit);
getReadOnly = closeAndSetNull(getReadOnly);
getGeneratedKeys = closeAndSetNull(getGeneratedKeys);
getLockMode = closeAndSetNull(getLockMode);
setLockMode = closeAndSetNull(setLockMode);
getQueryTimeout = closeAndSetNull(getQueryTimeout);
setQueryTimeout = closeAndSetNull(setQueryTimeout);
} finally {
session.close();
}
}
} finally {
session = null;
}
}
} catch (Throwable e) {
throw logAndConvert(e);
}
}
private CommandInterface closeAndSetNull(CommandInterface command) {
if (command != null) {
command.close();
}
return null;
}
/**
* Switches auto commit on or off. Calling this function does not commit the
* current transaction.
*
* @param autoCommit
* true for auto commit on, false for off
* @throws SQLException
* if the connection is closed
*/
public synchronized void setAutoCommit(boolean autoCommit) throws SQLException {
try {
if (debug()) {
debugCode("setAutoCommit(" + autoCommit + ");");
}
checkClosed();
if (autoCommit) {
setAutoCommitTrue = prepareCommand("SET AUTOCOMMIT TRUE", setAutoCommitTrue);
setAutoCommitTrue.executeUpdate();
} else {
setAutoCommitFalse = prepareCommand("SET AUTOCOMMIT FALSE", setAutoCommitFalse);
setAutoCommitFalse.executeUpdate();
}
} catch (Throwable e) {
throw logAndConvert(e);
}
}
/**
* Gets the current setting for auto commit.
*
* @return true for on, false for off
* @throws SQLException
* if the connection is closed
*/
public synchronized boolean getAutoCommit() throws SQLException {
try {
checkClosed();
debugCodeCall("getAutoCommit");
return getInternalAutoCommit();
} catch (Throwable e) {
throw logAndConvert(e);
}
}
private boolean getInternalAutoCommit() throws SQLException {
getAutoCommit = prepareCommand("CALL AUTOCOMMIT()", getAutoCommit);
ResultInterface result = getAutoCommit.executeQuery(0, false);
result.next();
boolean autoCommit = result.currentRow()[0].getBoolean().booleanValue();
result.close();
return autoCommit;
}
/**
* Commits the current transaction. This call has only an effect if
* auto commit is switched off.
*
* @throws SQLException
* if the connection is closed
*/
public synchronized void commit() throws SQLException {
try {
debugCodeCall("commit");
checkClosed();
commit = prepareCommand("COMMIT", commit);
commit.executeUpdate();
} catch (Throwable e) {
throw logAndConvert(e);
}
}
/**
* Rolls back the current transaction. This call has only an effect if
* auto commit is switched off.
*
* @throws SQLException
* if the connection is closed
*/
public synchronized void rollback() throws SQLException {
try {
debugCodeCall("rollback");
checkClosed();
rollbackInternal();
} catch (Throwable e) {
throw logAndConvert(e);
}
}
/**
* Returns true if this connection has been closed.
*
* @return true if close was called
*/
public boolean isClosed() throws SQLException {
try {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -