JDBC事务–自动提交

通过MYSQLIO执行IO操作。

commit=true/false,代码执行是一样的,都flush出去了,只是服务器端没有执行。

package com.zhuguang.jack.jdbc;

import java.sql.*;

public class JDBCTransationTest {
    public static void main(String[] args) {
        Connection connection = null;
        try {
            connection = getConnection();
            connection.setAutoCommit(false);// 执行之后不提交事务。对于Select没有影响, 但对于Insert和Update的话, 没有提交数据就不会被修改
            // 用法大多数是在要执行多条语句才提交。
            insertTest(connection);
//            insertTest1(connection);
            connection.commit();
            connection.rollback();
        } catch (ClassNotFoundException e) {
        } catch (SQLException e) {
            try {
                connection.rollback();//只要执行有异常,就要rollback , 这一步必不可少
                //如果没有在执行出现异常的时候进行回滚。如果在执行第一条语句之后出现异常,
                //con既没有提交也没有回滚,表就会被锁住(如果oracle数据库就是行锁),而这个锁却没有机会释放。
            } catch (SQLException e1) {
            }
        } finally {
            if (connection != null) {
                try {
                    selectAll(connection);
                    connection.close();// 关闭Connection的代码有被Mark掉, 是想呈现conn.setAutoCommit(false)的效果。
                    // 原因是在 Connection Close的时候会执行一次Commit.

                    // 而如果Connection是在应用服务器中使用连接池的话, Connection就不会被Close, 也就不会执行Commit.

                    //可能在执行con.close()的时候会释放锁,但还是如果应用服务器使用了数据库连接池,连接不会被断开。
                } catch (SQLException e) {
                }
            }
        }
    }

    public static void insertTest(Connection con) throws SQLException {
        PreparedStatement stmt = con.prepareStatement("insert into money(name,money) values (?,?)");
        stmt.setString(1, "JACK2");
        stmt.setDouble(2, 100.0);
        stmt.executeUpdate();
        System.out.println("Data inserted successfully");
        stmt.close();
    }

    public static void insertTest1(Connection con) throws SQLException {
        PreparedStatement stmt = con.prepareStatement("insert into money(name,money) values (?,?)");
        stmt.setString(1, "JACK3");
        stmt.setDouble(2, 100.10);
        stmt.executeUpdate();
        System.out.println("Data inserted successfully");
        stmt.close();
    }

    public static void selectAll(Connection con) throws SQLException {
        Statement st = con.createStatement();
        ResultSet rs = st.executeQuery("select * from money");
        System.out.println("============test============");
        while (rs.next()) {
            System.out.println(rs.getString("momey"));
        }
        ResultSet rs1 = st.executeQuery("select * from money");
        System.out.println("============test1============");
        while (rs1.next()) {
            System.out.println(rs1.getString("momey"));
        }
        st.close();
    }

    public static Connection getConnection() throws ClassNotFoundException, SQLException {
        Connection con = null;
        Class.forName("com.mysql.jdbc.Driver");
        con = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/account?useUnicode=true&characterEncoding=utf-8&useSSL=false", "root", "123456");
        System.out.println("DB Connection created successfully");
        return con;
    }
}
Class.forName("com.mysql.jdbc.Driver");

public class Driver extends NonRegisteringDriver implements java.sql.Driver {
    static {
        try {
            java.sql.DriverManager.registerDriver(new Driver());   //把Driver给注册到自己的驱动程序管理器(DriverManager)中
        }
    public Driver() throws SQLException {
    }
}
Class.forName得到的class是已经初始化完成的
Classloder.loaderClass得到的class是没有初始化的

public static synchronized void registerDriver(java.sql.Driver driver, DriverAction da) {
        if(driver != null) {
            registeredDrivers.addIfAbsent(new DriverInfo(driver, da));
        }
    }
public static Connection getConnection(String url, String user, String password)   {
        java.util.Properties info = new java.util.Properties();
        return (getConnection(url, info, Reflection.getCallerClass()));
    }
private static Connection getConnection( String url, java.util.Properties info, Class caller)   {
        for(DriverInfo aDriver : registeredDrivers) {
            if(isDriverAllowed(aDriver.driver, callerCL)) {
                try {
                    Connection con = aDriver.driver.connect(url, info);
                    if (con != null) {
                        return (con);  //com.mysql.jdbc.JDBC4Connection@221af3c0
                    }
                }
            }
        }
    }
NonRegisteringDriver类:
public Connection connect(String url, Properties info) {
       Connection newConn = com.mysql.jdbc.ConnectionImpl.getInstance(host(props), port(props), props, database(props), url);    //props = {HOST=127.0.0.1, user=root, HOST.1=127.0.0.1, password=123456, DBNAME=account, PORT=3306, NUM_HOSTS=1, PORT.1=3306},url = jdbc:mysql://127.0.0.1:3306/account,
       return newConn;   //com.mysql.jdbc.JDBC4Connection@221af3c0
    }
ConnectionImpl类:
protected static Connection getInstance(String hostToConnectTo, int portToConnectTo, Properties info, String databaseToConnectTo, String url) {
        return (Connection) Util.handleNewInstance(JDBC_4_CONNECTION_CTOR,
                new Object[] { hostToConnectTo, Integer.valueOf(portToConnectTo), info, databaseToConnectTo, url }, null);
    }
public static final Object handleNewInstance(Constructor ctor, Object[] args, ExceptionInterceptor exceptionInterceptor) {
            return ctor.newInstance(args);     //public com.mysql.jdbc.JDBC4Connection ,args = [127.0.0.1, 3306, {HOST=127.0.0.1, user=root, HOST.1=127.0.0.1, password=123456, DBNAME=account, PORT=3306, NUM_HOSTS=1, PORT.1=3306}, account, jdbc:mysql://127.0.0.1:3306/account]
    }
JDBC4Connection类:
public JDBC4Connection(String hostToConnectTo, int portToConnectTo, Properties info, String databaseToConnectTo, String url) throws SQLException {
        super(hostToConnectTo, portToConnectTo, info, databaseToConnectTo, url);
    }
public ConnectionImpl(String hostToConnectTo, int portToConnectTo, Properties info, String databaseToConnectTo, String url)  {

        this.origHostToConnectTo = hostToConnectTo;    //127.0.0.1
        this.origPortToConnectTo = portToConnectTo;   //3306
        this.origDatabaseToConnectTo = databaseToConnectTo;   //account

        this.port = portToConnectTo;    //3306

        this.database = databaseToConnectTo;   //account
        this.myURL = url;    //jdbc:mysql://127.0.0.1:3306/account
        this.user = info.getProperty(NonRegisteringDriver.USER_PROPERTY_KEY);    //root
        this.password = info.getProperty(NonRegisteringDriver.PASSWORD_PROPERTY_KEY);    //123456

        this.props = info;    //{HOST=127.0.0.1, user=root, HOST.1=127.0.0.1, password=123456, DBNAME=account, PORT=3306, NUM_HOSTS=1, PORT.1=3306}
        try {
            this.dbmd = getMetaData(false, false);
            initializeSafeStatementInterceptors();
            createNewIO(false);
            unSafeStatementInterceptors();
        }
        NonRegisteringDriver.trackConnection(this);
    }
public void createNewIO(boolean isForReconnect) throws SQLException {
        synchronized (getConnectionMutex()) {
            if (!getHighAvailability()) {
                connectOneTryOnly(isForReconnect, mergedProps);
                return;
            }
        }
    }
private void connectOneTryOnly(boolean isForReconnect, Properties mergedProps) throws SQLException {
        try {
            coreConnect(mergedProps);
            return;
        }
    }
private void coreConnect(Properties mergedProps) throws SQLException, IOException {
        int newPort = 3306;
        String newHost = "localhost";
        this.serverVariables.put("character_set_server", "utf8");//{character_set_server=utf8}

        this.io = new MysqlIO(newHost, newPort, mergedProps, getSocketFactoryClassName(), getProxy(), getSocketTimeout(),
                this.largeRowSizeThreshold.getValueAsInt());    //com.mysql.jdbc.MysqlIO@76a3e297,通过MYSQLIO执行IO操作。
        this.io.doHandshake(this.user, this.password, this.database);
    }
public MysqlIO(String host, int port, Properties props, String socketFactoryClassName, MySQLConnection conn, int socketTimeout, int useBufferRowSizeThreshold)  {
        this.connection = conn;    //com.mysql.jdbc.JDBC4Connection@7d0587f1
        try {
            this.mysqlConnection = this.socketFactory.connect(this.host, this.port, props);   //返回Socket[addr=/127.0.0.1,port=3306,localport=59593]

            this.mysqlConnection = this.socketFactory.beforeHandshake();    //Socket[addr=/127.0.0.1,port=3306,localport=59593]
        }
    }
StandardSocketFactory类:
public Socket connect(String hostname, int portNumber, Properties props) throws SocketException, IOException {
        if (props != null) {
                for (int i = 0; i < possibleAddresses.length; i++) {
                    try {
                        this.rawSocket = createSocket(props);
                        configureSocket(this.rawSocket, props);   //配置socket
                        InetSocketAddress sockAddr = new InetSocketAddress(possibleAddresses[i], this.port);    ///127.0.0.1:3306
                        this.rawSocket.connect(sockAddr, getRealTimeout(connectTimeout));   //连接数据库
                        break;
                    }
                }
                resetLoginTimeCountdown();
                return this.rawSocket;    //Socket[addr=/127.0.0.1,port=3306,localport=59422]
            }
        }
    }
Socket类:
public void connect(SocketAddress endpoint, int timeout) throws IOException {
        InetSocketAddress epoint = (InetSocketAddress) endpoint;
        InetAddress addr = epoint.getAddress ();
        int port = epoint.getPort();
        checkAddress(addr, "connect");
        if (!oldImpl)
            impl.connect(epoint, timeout);
    }
SocksSocketImpl类:
super.connect(epoint, remainingMillis(deadlineMillis));
AbstractPlainSocketImpl类:
connectToAddress(this.address, port, timeout);
doConnect(address, port, timeout);    ///127.0.0.1,3306,0
synchronized void doConnect(InetAddress address, int port, int timeout) throws IOException {
        try {
            try {
                socketConnect(address, port, timeout);
            }
        }
    }
DualStackPlainSocketImpl类:
connectResult = connect0(nativefd, address, port);    //native方法

不设置 connection.setAutoCommit(false);是在PreparedStatement.executeUpdate();时候就加到数据库了。

不设置 connection.setAutoCommit(false);connection.rollback();会报错,com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: Can’t call rollback when autocommit=true

设置 connection.setAutoCommit(false);是在connection.commit();时候就加到数据库了。

设置 connection.setAutoCommit(false);connection.close();并不会提交数据,再次connection.commit();就会报错MySQLNonTransientConnectionException: No operations allowed after connection closed.

不设置 connection.setAutoCommit(false);是在PreparedStatement.executeUpdate();时候
stmt = com.mysql.jdbc.JDBC42PreparedStatement@f0f2775: insert into money(name,money) values ('JACK2',100.0)
public int executeUpdate() throws SQLException {
        return Util.truncateAndConvertToInt(executeLargeUpdate());
    }
public long executeLargeUpdate() throws SQLException {
        return executeUpdateInternal(true, false);
    }
return executeUpdateInternal(this.parameterValues, this.parameterStreams, this.isStream, this.streamLengths, this.isNull, isBatch);    //parameterValues = [[39, 74, 65, 67, 75, 50, 39], [49, 48, 48, 46, 48]] = 'JACK2',100.0
protected long executeUpdateInternal(byte[][] batchedParameterStrings, InputStream[] batchedParameterStreams, boolean[] batchedIsStream,  int[] batchedStreamLengths, boolean[] batchedIsNull, boolean isReallyBatch)   {
        synchronized (checkClosed().getConnectionMutex()) {
            MySQLConnection locallyScopedConn = this.connection;   //com.mysql.jdbc.JDBC4Connection@345965f2
            Buffer sendPacket = fillSendPacket(batchedParameterStrings, batchedParameterStreams, batchedIsStream, batchedStreamLengths);    //batchedParameterStrings = [[39, 74, 65, 67, 75, 50, 39], [49, 48, 48, 46, 48]] = 'JACK2',100.0,返回3 insert.into.money(name,money).values.('JACK2',100.0)
            rs = executeInternal(-1, sendPacket, false, false, null, isReallyBatch);
            return this.updateCount;   //1
        }
    }
protected Buffer fillSendPacket(byte[][] batchedParameterStrings, InputStream[] batchedParameterStreams, boolean[] batchedIsStream,  int[] batchedStreamLengths) {
        synchronized (checkClosed().getConnectionMutex()) {
            Buffer sendPacket = this.connection.getIO().getSharedSendPacket();
            sendPacket.clear();
            sendPacket.writeByte((byte) MysqlDefs.QUERY);   //sendPacket插入QUERY=3,
            for (int i = 0; i < batchedParameterStrings.length; i++) {
                sendPacket.writeBytesNoNull(this.staticSqlStrings[i]);
                if (batchedIsStream[i]) {
                    streamToBytes(sendPacket, batchedParameterStreams[i], true, batchedStreamLengths[i], useStreamLengths);
                } else {
                    sendPacket.writeBytesNoNull(batchedParameterStrings[i]);
                }
            }
            sendPacket.writeBytesNoNull(this.staticSqlStrings[batchedParameterStrings.length]);
            return sendPacket;    //3 insert.into.money(name,money).values.('JACK2',100.0)
        }
    }
protected ResultSetInternalMethods executeInternal(int maxRowsToRetrieve, Buffer sendPacket, boolean createStreamingResultSet, boolean queryIsSelectOnly,
            Field[] metadataFromCache, boolean isBatch) throws SQLException {
        synchronized (checkClosed().getConnectionMutex()) {
            try {
                MySQLConnection locallyScopedConnection = this.connection;    //com.mysql.jdbc.JDBC4Connection@345965f2
                try {
                    rs = locallyScopedConnection.execSQL(this, null, maxRowsToRetrieve, sendPacket, this.resultSetType, this.resultSetConcurrency, createStreamingResultSet, this.currentCatalog, metadataFromCache, isBatch);
    }
public ResultSetInternalMethods execSQL(StatementImpl callingStatement, String sql, int maxRows, Buffer packet, int resultSetType, int resultSetConcurrency,  {
                return this.io.sqlQueryDirect(callingStatement, null, null, packet, maxRows, resultSetType, resultSetConcurrency, streamResults, catalog, cachedMetadata);   //通过MYSQLIO执行IO操作。
    }
Buffer resultPacket = sendCommand(MysqlDefs.QUERY, null, queryPacket, false, null, 0);     //queryPacket = 3 insert.into.money(name,money).values.('JACK2',100.0)
send(queryPacket, queryPacket.getPosition());     //queryPacket = 3 insert.into.money(name,money).values.('JACK2',100.0)

this.mysqlOutput.write(packetToSend.getByteBuffer(), 0, packetLen);//packetToSend = insert into money(name,money) values ('JACK2',100.0)
this.mysqlOutput.flush();   //数据插入到数据库了,mysqlOutput = SET autocommit=1
connection.setAutoCommit(false);

public void setAutoCommit(final boolean autoCommitFlag) throws SQLException {
        synchronized (getConnectionMutex()) {
            try {
                if (this.transactionsSupported) {
                    this.autoCommit = autoCommitFlag;    //false,不自动提交
                    if (needsSetOnServer) {
                        execSQL(null, autoCommitFlag ? "SET autocommit=1" : "SET autocommit=0", -1, null, DEFAULT_RESULT_SET_TYPE,
                                DEFAULT_RESULT_SET_CONCURRENCY, false, this.database, null, false);
                    }
                }
            }
            return;
        }
    }
public ResultSetInternalMethods execSQL(StatementImpl callingStatement, String sql, int maxRows, Buffer packet, int resultSetType, int resultSetConcurrency,
            boolean streamResults, String catalog, Field[] cachedMetadata, boolean isBatch) throws SQLException {
        synchronized (getConnectionMutex()) {
            try {
                if (packet == null) {
                    return this.io.sqlQueryDirect(callingStatement, sql, encoding, null, maxRows, resultSetType, resultSetConcurrency, streamResults, catalog,  cachedMetadata);  //通过MYSQLIO执行IO操作。
                }
            }
        }
    }
this.sendPacket.writeStringNoNull(query, characterEncoding, this.connection.getServerCharset(),
                                    this.connection.parserKnowsUnicode(), this.connection);    //query = SET autocommit=0
Buffer resultPacket = sendCommand(MysqlDefs.QUERY, null, queryPacket, false, null, 0);     //queryPacket = SET autocommit=0
send(queryPacket, queryPacket.getPosition());
this.mysqlOutput.write(packetToSend.getByteBuffer(), 0, packetLen);
this.mysqlOutput.flush();   //SET autocommit=0执行flush操作。mysqlOutput = SET autocommit=1 */
insertTest(connection);

public static void insertTest(Connection con) throws SQLException {
        PreparedStatement stmt = con.prepareStatement("insert into money(name,money) values (?,?)");
        stmt.setString(1, "JACK2");
        stmt.setDouble(2, 100.0);
        stmt.executeUpdate();
        System.out.println("Data inserted successfully");
        stmt.close();
    }
public java.sql.PreparedStatement prepareStatement(String sql) throws SQLException {
        return prepareStatement(sql, DEFAULT_RESULT_SET_TYPE, DEFAULT_RESULT_SET_CONCURRENCY);
    }
public java.sql.PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency) throws SQLException {
        synchronized (getConnectionMutex()) {
            String nativeSql = getProcessEscapeCodesForPrepStmts() ? nativeSQL(sql) : sql;    //insert into money(name,money) values (?,?)

            if (this.useServerPreparedStmts && canServerPrepare) {
            } else {
                pStmt = (PreparedStatement) clientPrepareStatement(nativeSql, resultSetType, resultSetConcurrency, false);
            }
            return pStmt;    //com.mysql.jdbc.JDBC42PreparedStatement@f0f2775: insert into money(name,money) values (** NOT SPECIFIED **,** NOT SPECIFIED **)
        }
    }
public java.sql.PreparedStatement clientPrepareStatement(String sql, int resultSetType, int resultSetConcurrency, boolean processEscapeCodesIfNeeded)  {
        String nativeSql = processEscapeCodesIfNeeded && getProcessEscapeCodesForPrepStmts() ? nativeSQL(sql) : sql;   //insert into money(name,money) values (?,?)

        if (getCachePreparedStatements()) {
        } else {
            pStmt = com.mysql.jdbc.PreparedStatement.getInstance(getMultiHostSafeProxy(), nativeSql, this.database);    //返回com.mysql.jdbc.JDBC42PreparedStatement@f0f2775: insert into money(name,money) values (** NOT SPECIFIED **,** NOT SPECIFIED **)
        }

        pStmt.setResultSetType(resultSetType);
        pStmt.setResultSetConcurrency(resultSetConcurrency);

        return pStmt;
    }
protected static PreparedStatement getInstance(MySQLConnection conn, String sql, String catalog) throws SQLException {
        return (PreparedStatement) Util.handleNewInstance(JDBC_4_PSTMT_3_ARG_CTOR, new Object[] { conn, sql, catalog }, conn.getExceptionInterceptor());    //JDBC_4_PSTMT_3_ARG_CTOR = public com.mysql.jdbc.JDBC42PreparedStatement(com.mysql.jdbc.MySQLConnection, String, String) ,conn = JDBC4Connection,sql = insert into money(name,money) values (?,?),catalog = account,
    }
public static final Object handleNewInstance(Constructor ctor, Object[] args, ExceptionInterceptor exceptionInterceptor) throws SQLException {
        try {
            return ctor.newInstance(args);
        }
        }
    }
JDBC42PreparedStatement类:
public JDBC42PreparedStatement(MySQLConnection conn, String sql, String catalog) throws SQLException {
        super(conn, sql, catalog);   //conn=
    }
public JDBC4PreparedStatement(MySQLConnection conn, String sql, String catalog) throws SQLException {
        super(conn, sql, catalog);
    }
public PreparedStatement(MySQLConnection conn, String sql, String catalog) throws SQLException {
        super(conn, catalog);   ////com.mysql.jdbc.JDBC4Connection@221af3c0,account
        this.originalSql = sql;   //insert into money(name,money) values (?,?)

        this.dbmd = this.connection.getMetaData();   //JDBC4DatabaseMetaData
    }
public StatementImpl(MySQLConnection c, String catalog) throws SQLException {
        this.connection = c;   //com.mysql.jdbc.JDBC4Connection@221af3c0
        this.currentCatalog = catalog;   //account

        if (!this.connection.getDontTrackOpenResources()) {
            this.connection.registerStatement(this);   //this = JDBC42PreparedStatement
        }
    }
stmt.setString(1, "JACK2");

public void setString(int parameterIndex, String x) throws SQLException {
        synchronized (checkClosed().getConnectionMutex()) {
            if (x == null) {
            } else {
                String parameterAsString = x;    //JACK222,内容
                byte[] parameterAsBytes = null;

                if (!this.isLoadDataQuery) {
                    if (needsQuoted) {
                        parameterAsBytes = StringUtils.getBytesWrapped(parameterAsString, '\'', '\'', this.charConverter, this.charEncoding,
                                this.connection.getServerCharset(), this.connection.parserKnowsUnicode(), getExceptionInterceptor());  //parameterAsBytes = 'JACK2'
                    } else {
                    }
                }

                setInternal(parameterIndex, parameterAsBytes);  //设置第一个?为JACK222内容,parameterIndex = 1,parameterAsBytes = 'JACK2'

                this.parameterTypes[parameterIndex - 1 + getParameterIndexOffset()] = Types.VARCHAR;    //设置第一个?参数类型为VARCHAR
            }
        }
    }
protected final void setInternal(int paramIndex, byte[] val) throws SQLException {
        synchronized (checkClosed().getConnectionMutex()) {
            this.isStream[paramIndex - 1 + parameterIndexOffset] = false;
            this.isNull[paramIndex - 1 + parameterIndexOffset] = false;
            this.parameterStreams[paramIndex - 1 + parameterIndexOffset] = null;
            this.parameterValues[paramIndex - 1 + parameterIndexOffset] = val;    //parameterValues就是参数,设置第一个?为JACK222内容
        }
    }
stmt.executeUpdate();

public int executeUpdate() throws SQLException {
        return Util.truncateAndConvertToInt(executeLargeUpdate());
    }
public long executeLargeUpdate() throws SQLException {
        return executeUpdateInternal(true, false);
    }
protected long executeUpdateInternal(boolean clearBatchedGeneratedKeysAndWarnings, boolean isBatch) throws SQLException {
        synchronized (checkClosed().getConnectionMutex()) {
            return executeUpdateInternal(this.parameterValues, this.parameterStreams, this.isStream, this.streamLengths, this.isNull, isBatch);
        }
    }
protected long executeUpdateInternal(byte[][] batchedParameterStrings, InputStream[] batchedParameterStreams, boolean[] batchedIsStream, int[] batchedStreamLengths, boolean[] batchedIsNull, boolean isReallyBatch)   {

        synchronized (checkClosed().getConnectionMutex()) {
            MySQLConnection locallyScopedConn = this.connection;     //com.mysql.jdbc.JDBC4Connection@221af3c0
            Buffer sendPacket = fillSendPacket(batchedParameterStrings, batchedParameterStreams, batchedIsStream, batchedStreamLengths);    //sendPacket  = 3 insert.into.money(name,money).values.('JACK2',100.0)

            rs = executeInternal(-1, sendPacket, false, false, null, isReallyBatch);

            return this.updateCount;
        }
    }
protected ResultSetInternalMethods executeInternal(int maxRowsToRetrieve, Buffer sendPacket, boolean createStreamingResultSet, boolean queryIsSelectOnly,
            Field[] metadataFromCache, boolean isBatch) throws SQLException {
        synchronized (checkClosed().getConnectionMutex()) {
                    rs = locallyScopedConnection.execSQL(this, null, maxRowsToRetrieve, sendPacket, this.resultSetType, this.resultSetConcurrency,
                            createStreamingResultSet, this.currentCatalog, metadataFromCache, isBatch);    //sendPacket  = 3 insert.into.money(name,money).values.('JACK2',100.0)
                return rs;
            }
        }
    }
public ResultSetInternalMethods execSQL(StatementImpl callingStatement, String sql, int maxRows, Buffer packet, int resultSetType, int resultSetConcurrency,  {
                return this.io.sqlQueryDirect(callingStatement, null, null, packet, maxRows, resultSetType, resultSetConcurrency, streamResults, catalog, cachedMetadata);   //通过MYSQLIO执行IO操作。
    }
Buffer resultPacket = sendCommand(MysqlDefs.QUERY, null, queryPacket, false, null, 0);     //queryPacket = 3 insert.into.money(name,money).values.('JACK2',100.0)
send(queryPacket, queryPacket.getPosition());     //queryPacket = 3 insert.into.money(name,money).values.('JACK2',100.0)
this.mysqlOutput.write(packetToSend.getByteBuffer(), 0, packetLen);   //packetToSend = insert into money(name,money) values ('JACK2',100.0)
this.mysqlOutput.flush();   //数据没有插入到数据库了。commit=true/false,代码执行是一样的,都flush出去了,只是服务器端没有执行。mysqlOutput = SET autocommit=0*/
stmt.close();

public void close() throws SQLException {
        realClose(true, true);
    }
protected void realClose(boolean calledExplicitly, boolean closeOpenResults) throws SQLException {
        MySQLConnection locallyScopedConn = this.connection;    //com.mysql.jdbc.JDBC4Connection@221af3c0

        synchronized (locallyScopedConn.getConnectionMutex()) {

            super.realClose(calledExplicitly, closeOpenResults);

            this.dbmd = null;     //com.mysql.jdbc.JDBC4DatabaseMetaData里面有数据库信息和表信息
            this.originalSql = null;  //insert into money(name,money) values (?,?)
            this.staticSqlStrings = null;  //insert into money(name,money) values (?,?)
            this.parameterValues = null;    //'JACK2'  ,100.0
            this.parameterStreams = null;
            this.isStream = null;
            this.streamLengths = null;
            this.isNull = null;
            this.streamConvertBuf = null;
            this.parameterTypes = null;
        }
    }
protected void realClose(boolean calledExplicitly, boolean closeOpenResults) throws SQLException {
        MySQLConnection locallyScopedConn = this.connection;    //com.mysql.jdbc.JDBC4Connection@221af3c0

        if (!locallyScopedConn.getDontTrackOpenResources()) {
            locallyScopedConn.unregisterStatement(this);   //移除JDBC42PreparedStatement
        }

        if (closeOpenResults) {
            if (this.results != null) {
                try {
                    this.results.close();
                }
            }
            closeAllOpenResults();
        }
        this.isClosed = true;
        this.results = null;
        this.generatedKeysResults = null;
        this.connection = null;
        this.warningChain = null;
        this.openResults = null;
        this.batchedGeneratedKeys = null;
        this.localInfileInputStream = null;
        this.pingTarget = null;
    }
public void close() throws SQLException {
        realClose(true);
    }
public void realClose(boolean calledExplicitly) throws SQLException {
        MySQLConnection locallyScopedConn = this.connection;    //com.mysql.jdbc.JDBC4Connection@221af3c0
        synchronized (locallyScopedConn.getConnectionMutex()) {
            try {
                if (this.useUsageAdvisor) {
            } finally {
                if (this.owningStatement != null && calledExplicitly) {
                    this.owningStatement.removeOpenResultSet(this);
                }
            }
        }
    }
connection.commit();

public void commit() throws SQLException {
        synchronized (getConnectionMutex()) {
            try {
                if (this.autoCommit && !getRelaxAutoCommit()) {
                } else if (this.transactionsSupported) {
                    execSQL(null, "commit", -1, null, DEFAULT_RESULT_SET_TYPE, DEFAULT_RESULT_SET_CONCURRENCY, false, this.database, null, false);
                }
            }   finally {
                this.needsPing = this.getReconnectAtTxEnd();
            }
        }
        return;
    }
public ResultSetInternalMethods execSQL(StatementImpl callingStatement, String sql, int maxRows, Buffer packet, int resultSetType, int resultSetConcurrency,
            boolean streamResults, String catalog, Field[] cachedMetadata, boolean isBatch) throws SQLException {
        synchronized (getConnectionMutex()) {
            try {
                if (packet == null) {
                    return this.io.sqlQueryDirect(callingStatement, sql, encoding, null, maxRows, resultSetType, resultSetConcurrency, streamResults, catalog, cachedMetadata);    //io = com.mysql.jdbc.MysqlIO@709ba3fb,  //通过MYSQLIO执行IO操作。
                }
        }
    }
final ResultSetInternalMethods sqlQueryDirect(StatementImpl callingStatement, String query, String characterEncoding, Buffer queryPacket, int maxRows,
            int resultSetType, int resultSetConcurrency, boolean streamResults, String catalog, Field[] cachedMetadata) throws Exception {
        try {
            if (query != null) {
                this.sendPacket.writeByte((byte) MysqlDefs.QUERY);
                if (characterEncoding != null) {
                    if (this.platformDbCharsetMatches) {
                    } else {
                        if (StringUtils.startsWithIgnoreCaseAndWs(query, "LOAD DATA")) {
                        } else {
                            this.sendPacket.writeStringNoNull(query, characterEncoding, this.connection.getServerCharset(),
                                    this.connection.parserKnowsUnicode(), this.connection);
                        }
                    }
                }
                queryPacket = this.sendPacket;   //commit
            }
            Buffer resultPacket = sendCommand(MysqlDefs.QUERY, null, queryPacket, false, null, 0);   //通过socket发送commit

            ResultSetInternalMethods rs = readAllResults(callingStatement, maxRows, resultSetType, resultSetConcurrency, streamResults, catalog, resultPacket,
                    false, -1L, cachedMetadata);

        } finally {
            this.statementExecutionDepth--;
        }
send(queryPacket, queryPacket.getPosition());    //queryPacket = commit
this.mysqlOutput.write(packetToSend.getByteBuffer(), 0, packetLen);
this.mysqlOutput.flush();    //数据库有数据,mysqlOutput = commit into money(name,money) values ('JACK2',100.0)) */
connection.rollback();

public void rollback() throws SQLException {
        synchronized (getConnectionMutex()) {
            try {
                if (this.autoCommit && !getRelaxAutoCommit()) {
                } else if (this.transactionsSupported) {
                    try {
                        rollbackNoChecks();
                    }
                    }
                }
            }
        }
    }
private void rollbackNoChecks() throws SQLException {
        execSQL(null, "rollback", -1, null, DEFAULT_RESULT_SET_TYPE, DEFAULT_RESULT_SET_CONCURRENCY, false, this.database, null, false);
    }
return this.io.sqlQueryDirect(callingStatement, sql, encoding, null, maxRows, resultSetType, resultSetConcurrency, streamResults, catalog, cachedMetadata);

send(queryPacket, queryPacket.getPosition());   ///queryPacket = rollback

 this.mysqlOutput.write(packetToSend.getByteBuffer(), 0, packetLen);
 this.mysqlOutput.flush();     //mysqlOutput = rollbacknto money(name,money) values ('JACK2',100.0)

JDBC事务--自动提交

Original: https://www.cnblogs.com/yaowen/p/12259962.html
Author: 哈哈呵h
Title: JDBC事务–自动提交

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/546178/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球