# JDBC概述

# 什么是JDBC

  • JDBC,java database connectivity, 是java语言中,用来规范客户端程序,如何访问数据库的应用程序接口;

# 主要用途

  • 与数据库建立连接
  • 发送SQL语句
  • 处理查询结果

# JDBC原生编程

# 加载客户端驱动

class Main{
    static {
        try {
            Class.forName("com.mysql.jdbc.Driver");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}

# 获取连接

class Main{
    public Connection getConnection(){
        Connection connection=null;
        try {
            connection= DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/mytest", "root", "chenkaihai");
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return connection;
    }
}

# 操作数据库

class Main{
    public void statementSql(Connection connection){
    
        if(connection==null){
            return;
        }

        Statement statement= null;
                try {
                    statement = connection.createStatement();
                    boolean dmlResult= statement.execute("delete my_table where id = 'mykey' ");
                    System.out.println("dml结果:"+dmlResult);
                    ResultSet resultSet = statement.executeQuery("select * from my_table");
                    while (resultSet.next()){
                        System.out.println("dql结果:");
                        System.out.println(resultSet.getString(1));
                        System.out.println(resultSet.getString(2));
                        System.out.println(resultSet.getString(3));
                        //....
        
                    }
                } catch (SQLException e) {
                    e.printStackTrace();
                }finally {
                    try {
                        statement.close();
                    } catch (SQLException e) {
                        e.printStackTrace();
                    }
        }
    }

}

# dql语句进行orm转换

  • 从ResultSet获取数据,并转成java POJO对象.

# java数据库编程

# 数据库事务控制

public interface Connection  extends Wrapper, AutoCloseable {
    void setAutoCommit(boolean autoCommit) throws SQLException;

    void setReadOnly(boolean readOnly) throws SQLException;

    void setTransactionIsolation(int level) throws SQLException;
    
    //省略其它抽象...
}

# spring项目设置隔离级别

  • 事务隔离 可以是 session级别的
public enum Isolation {
    DEFAULT(-1),
    READ_UNCOMMITTED(1),
    READ_COMMITTED(2),
    REPEATABLE_READ(4),
    SERIALIZABLE(8);

    private final int value;

    private Isolation(int value) {
        this.value = value;
    }

    public int value() {
        return this.value;
    }
}

@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface Transactional {
    @AliasFor("transactionManager")
    String value() default "";

    @AliasFor("value")
    String transactionManager() default "";

    Propagation propagation() default Propagation.REQUIRED;

    Isolation isolation() default Isolation.DEFAULT;

    int timeout() default -1;

    boolean readOnly() default false;

    Class<? extends Throwable>[] rollbackFor() default {};

    String[] rollbackForClassName() default {};

    Class<? extends Throwable>[] noRollbackFor() default {};

    String[] noRollbackForClassName() default {};
}

# 事务传播行为

  • 需要注意,事务传播行为是spring中的概念,属于客户端范畴。

  • 事务隔离级别,属于服务端范畴

  • 允许事务

public enum Propagation {
    REQUIRED(0),        //有就加入,没有就新建
    MANDATORY(2),       //必须有,不然报错
    REQUIRES_NEW(3),    //不管有没有都新建事务
    NESTED(6);          //有就嵌套事务执行,没有就跟REQUIRED一样。  嵌套事务外层会影响内层,内层不会影响外层

    private final int value;

    private Propagation(int value) {
        this.value = value;
    }

    public int value() {
        return this.value;
    }
}
  • 不允许事务
public enum Propagation {
    SUPPORTS(1),        //有就加入,没有就算了
    NOT_SUPPORTED(4),   //不支持事务,有就挂起
    NEVER(5);           //不支持事务,不然报错

    private final int value;

    private Propagation(int value) {
        this.value = value;
    }

    public int value() {
        return this.value;
    }
}

# JDBC底层理论

# 连接

package java.sql;
public interface Driver {
    Connection connect(String url, java.util.Properties info);
}
package com.mysql.cj.jdbc;
public class NonRegisteringDriver implements java.sql.Driver {
    
    public java.sql.Connection connect(String url, Properties info) throws SQLException {
        //xxx: 省略其它抽象...(负载之类的)
        return com.mysql.cj.jdbc.ConnectionImpl.getInstance(conStr.getMainHost());
    }
}
package java.sql;
public interface Connection  extends Wrapper, AutoCloseable {
 	Statement createStatement();
    
    void setAutoCommit(boolean autoCommit);
    
    void commit();
    
    void rollback();
    
    void close();
}
package com.mysql.cj.jdbc;
public class ConnectionImpl implements JdbcConnection, SessionEventListener, Serializable {
    
    private NativeSession session = null;
 	
    public ConnectionImpl(HostInfo hostInfo) throws SQLException {
     	createNewIO(false);
        //xxx:省略其它抽象...
    }
    
    public void createNewIO(boolean isForReconnect) {
     	synchronized (getConnectionMutex()) {
            //xxx:省略其它抽象,如是否重试的判断
         	connectOneTryOnly(isForReconnect); 
        }
    }
    
    private void connectOneTryOnly(boolean isForReconnect) throws SQLException {
     	this.session.connect(this.origHostInfo, this.user, this.password, this.database, getLoginTimeout(), c);
        //xxx: 省略其它抽象...
    }
}

public class NativeSession extends CoreSession implements Serializable {
 	public void connect(HostInfo hi, String user, String password, String database, int loginTimeout, TransactionEventHandler transactionManager)
            throws IOException {
       SocketConnection socketConnection = new NativeSocketConnection();
        socketConnection.connect(this.hostInfo.getHost(), this.hostInfo.getPort(), this.propertySet, getExceptionInterceptor(), this.log, loginTimeout);
        //xxx: 省略其它抽象...
    }
    
    public void quit() {
        try{
            ((NativeProtocol) this.protocol).quit();
        //xxx: 省略其它抽象,本质上是调用socket.shutdownInput(),会因为读取超时导致链路关闭
        }finally{
            this.socketConnection.forceClose();
            //xxx: 主要动作包括 inputStream.close(),outputStream.close(),socket.close()
        }
     	
    }
}

# 连接池

public class DruidDataSource extends DruidAbstractDataSource implements DruidDataSourceMBean, ManagedDataSource, Referenceable, Closeable, Cloneable, ConnectionPoolDataSource, MBeanRegistration {
 	
    // xxx:存储连接池中的连接
    private volatile DruidConnectionHolder[] connections;
    
    //xxx: 创建连接的线程
    private CreateConnectionThread           createConnectionThread;
    
    //xxx: 销毁连接的线程
    private DestroyConnectionThread          destroyConnectionThread;
    
    @Override
    public DruidPooledConnection getConnection() throws SQLException {
        return getConnection(maxWait);
    }
    
    public DruidPooledConnection getConnection(long maxWaitMillis) throws SQLException {
        init();
     	//xxx: 省略其它抽象...
        return getConnectionDirect(maxWaitMillis);
    }
    
    public void init() throws SQLException {
     	if (inited) {
            return;
        }
        
        //xxx: 解析驱动,常见的数据库如mysql,oracle等都可以实现自动识别驱动
        resolveDriver();
        
        //xxx: 线程开始操作..
        createAndStartCreatorThread();
        createAndStartDestroyThread();
    }
    
    public DruidPooledConnection getConnectionDirect(long maxWaitMillis) throws SQLException {
     	poolableConnection = getConnectionInternal(maxWaitMillis);
        //xxx: 省略其它抽象...
    }
    
    private DruidPooledConnection getConnectionInternal(long maxWait) throws SQLException {
        //xxx: 有则直接返回,无则创建连接(参数允许的情况下)
     	PhysicalConnectionInfo pyConnInfo = DruidDataSource.this.createPhysicalConnection();   
        //xxx: 省略其它抽象...
    }
    
    public PhysicalConnectionInfo createPhysicalConnection() throws SQLException {
        //xxx: 省略其它抽象...
     	conn = getDriver().connect(url, info);   
    }
    
}

public class CreateConnectionThread extends Thread {
 	public void run() {
        //xxx: 省略其它抽象,通过 CountDownLatch 结合 Condition实现线程循环操作
     	connection = createPhysicalConnection();   
    }
}

public class DestroyConnectionThread extends Thread {
 	public void run() {
        initedLatch.countDown();
     	 Thread.sleep(1000);
        //xxx: 省略其它抽象,通过线程休眠 实现线程机制
         destroyTask.run();
    }
}