数据库 connection 的本质

目前在网上看到有如下两种获取 connection 的办法:

第一种:
//3.创建Driver对象
Driver driver = (Driver)Class.forName(driverName).newInstance();

Properties info = new Properties(); //driver的connect方法中需要一个Properties型的参数
info.put(“user”, user);
info.put(“password”, password);

//4.使用driver的connect方法获取数据库连接
Connection conn = driver.connect(url, info);

第二种:
/3.加载驱动程序,即将数据库厂商提供的Driver接口实现类加载进内存;
// 该驱动类中的静态代码块包含有注册驱动的程序,在加载类时将被执行
Class.forName(driverName);

//4.通过DriverManager类的静态方法getConnection获取数据连接
Connection conn = DriverManager.getConnection(url, user, password);

总结来说就算一种是通过 Dirver 来获取,一种是通过 DriverManager 来获取.

然后进一步调试源码,发现通过 DriverManager 来获取,最终还是转换成通过 Driver 来获取,如下:

所以,这两者本质上是一个东西.

那下面在说下 connection 是什么?或者说 connection 有哪些东西?

说这个之前,我们先看下 Driver 是啥?或者说我们先自定义一个 Driver.

public class SSDriver implements Driver {
private final String URL_PREFIX = “jdbc:smalldb”;

static SSDriver ssDriver;

static {
    ssDriver = new SSDriver();
    try {
        DriverManager.registerDriver(ssDriver);
    } catch (SQLException e) {
        e.printStackTrace();
    }
}

// 解析 url
// 例:jdbc:mysql://192.168.0.105:3306/shgb_fz?useUnicode=true&characterEncoding=UTF8&
// autoReconnect=true&zeroDateTimeBehavior=convertToNull
private Properties parse(String url, Properties info) throws SQLException {
    Properties props = (Properties)info.clone();
    if(!acceptsURL(url)){
        return props;
    }
    int idx1 = url.indexOf(':', 5); // search after "jdbc:"
    int idx2 = url.indexOf('?');
    if(idx1 > 0){
        String dbPath = (idx2 > 0) ? url.substring(idx1 + 1, idx2) : url.substring(idx1 + 1);
        props.setProperty("dbpath", dbPath);
    }
    if(idx2 > 0){
        String propsString = url.substring(idx2 + 1);
        StringTokenizer tok = new StringTokenizer(propsString, ";");
        while(tok.hasMoreTokens()){
            String keyValue = tok.nextToken().trim();
            if(keyValue.length() > 0){
                idx1 = keyValue.indexOf('=');
                if(idx1 > 0){
                    String key = keyValue.substring(0, idx1).toLowerCase().trim();
                    String value = keyValue.substring(idx1 + 1).trim();
                    props.put(key, value);
                }else{
                    throw SmallDBException.create(Language.CUSTOM_MESSAGE, "Missing equal in property:" + keyValue);
                }
            }
        }
    }
    return props;
}

public Connection connect(String url, Properties info) throws SQLException {
    if(acceptsURL(url)){
        return new SSConnection(parse(url, info));
    }
    return null;
}

// 检查该 URL 是否合法.
public boolean acceptsURL(String url) throws SQLException {
    return url.startsWith(URL_PREFIX);
}

public DriverPropertyInfo[] getPropertyInfo(String url, Properties info) throws SQLException {
    Properties props = parse(url, info);
    DriverPropertyInfo[] driverInfos = new DriverPropertyInfo[1];
    driverInfos[0] = new DriverPropertyInfo("dbpath", props.getProperty("dbpath"));
    return driverInfos;
}

public int getMajorVersion() {
    return 0;
}

public int getMinorVersion() {
    return 20;
}

public boolean jdbcCompliant() {
    return true;
}

public Logger getParentLogger() throws SQLFeatureNotSupportedException {
    return null;
}

}

然后看下 connection 中做了那些事:

/**

  • Connection 应该包含哪些信息了?

  • 1.连接那个数据库

  • 2.事务隔离级别

  • 3.是否自动提交
    */
    public class SSConnection implements Connection {

    private boolean autoCommit = true;
    private Database database;
    int isolationLevel = TRANSACTION_READ_COMMITTED;
    // 待提交的集合.
    private List commitPages = new ArrayList();
    // 事务开启时间
    private long transactionTime;

    private final SSDatabaseMetadata metadata;

    private int holdability;

    final Logger log;

    public SSConnection(Properties props) throws SQLException {
    SmallDBException.setLanguage(props.get(“locale”));
    log = new Logger();
    String name = props.getProperty(“dbpath”);
    boolean create = “true”.equals(props.getProperty(“create”));
    database = Database.getDatabase(name, this, create);
    metadata = new SSDatabaseMetaData(this);
    }

    SSConnection(SSConnection conn){
    database = conn.database;
    metadata = conn.metadata;
    log = conn.log;
    }

    Database getDatabase(boolean returnNull) throws SQLException{
    testClosedConnection();
    // 打开数据的含义就是读文件.
    // 数据库数据的存储本质上也是文件的存储.
    if(!returnNull && database == null) throw SmallDBException.create(Language.DB_NOTCONNECTED);
    return database;
    }

    final void testClosedConnection() throws SQLException{
    if(isClosed()) throw SmallDBException.create(Language.CONNECTION_CLOSED);
    }

    Object getMonitor(){
    return this;
    }

    @Override
    public Statement createStatement() throws SQLException {
    return new SSStatement(this);
    }

    @Override
    public PreparedStatement prepareStatement(String sql) throws SQLException {
    return SSPreparedStatement(this, sql);
    }

    @Override
    public CallableStatement prepareCall(String sql) throws SQLException {
    return SSCallableStatement(this, sql);
    }

    @Override
    public String nativeSQL(String sql) throws SQLException {
    return sql;
    }

    @Override
    public void setAutoCommit(boolean autoCommit) throws SQLException {
    if(log.isLogging()) log.println(“AutoCommit:”+autoCommit);
    if(this.autoCommit != autoCommit){
    // 先提交,后改变
    commit();
    this.autoCommit = autoCommit;
    }
    }

    @Override
    public boolean getAutoCommit() throws SQLException {
    return autoCommit;
    }

    /**

    • Add a page for later commit or rollback.
      */
      void add(TransactionStep storePage) throws SQLException{
      testClosedConnection();
      synchronized(getMonitor()){
      commitPages.add(storePage);
      }
      }

    // TODO 待定
    @Override
    public void commit() throws SQLException {
    log.println(“Commit”);
    testClosedConnection();
    synchronized(getMonitor()){
    try{
    int count = commitPages.size();
    for(int i=0; i<count; i++){
    TransactionStep page = (TransactionStep)commitPages.get(i);
    page.commit();
    }
    for(int i=0; i<count; i++){
    TransactionStep page = (TransactionStep)commitPages.get(i);
    page.freeLock();
    }
    commitPages.clear();
    transactionTime = System.currentTimeMillis();
    }catch(Throwable e){
    rollback();
    throw SmallDBException.createFromException(e);
    }
    }
    }

    /**

    • Discard all changes of a file because it was deleted.
      */
      void rollbackFile(RandomAccessFile raFile) throws SQLException{
      testClosedConnection();
      // remove the all commits that point to this table
      synchronized(getMonitor()){
      for(int i = commitPages.size() - 1; i >= 0; i–){
      TransactionStep page = (TransactionStep)commitPages.get(i);
      if(page.raFile == raFile){
      page.rollback();
      page.freeLock();
      }
      }
      }
      }

    void rollback(int savepoint) throws SQLException{
    testClosedConnection();
    synchronized(getMonitor()){
    for(int i = commitPages.size() - 1; i >= savepoint; i–){
    TransactionStep page = (TransactionStep)commitPages.remove(i);
    page.rollback();
    page.freeLock();
    }
    }
    }

    @Override
    public void rollback() throws SQLException {
    log.println(“Rollback”);
    testClosedConnection();
    synchronized(getMonitor()){
    int count = commitPages.size();
    for(int i=0; i<count; i++){
    TransactionStep page = (TransactionStep)commitPages.get(i);
    page.rollback();
    page.freeLock();
    }
    commitPages.clear();
    transactionTime = System.currentTimeMillis();
    }
    }

    // 关闭前回滚
    @Override
    public void close() throws SQLException {
    rollback();
    database = null;
    commitPages = null;
    Database.closeConnection(this);
    }

    @Override
    public boolean isClosed() throws SQLException {
    return null == commitPages;
    }

    @Override
    public DatabaseMetaData getMetaData() throws SQLException {
    return metadata;
    }

    @Override
    public void setReadOnly(boolean readOnly) throws SQLException {
    //TODO Connection ReadOnly implementing
    }

    @Override
    public boolean isReadOnly() throws SQLException {
    return false;
    }

    @Override
    public void setCatalog(String catalog) throws SQLException {
    testClosedConnection();
    database = Database.getDatabase(catalog, this, false);
    }

    @Override
    public String getCatalog() throws SQLException {
    if(database == null)
    return “”;
    return database.getName();
    }

    @Override
    public void setTransactionIsolation(int level) throws SQLException {
    if(!metadata.supportsTransactionIsolationLevel(level)) {
    throw SmallSQLException.create(Language.ISOLATION_UNKNOWN, String.valueOf(level));
    }
    isolationLevel = level;
    }

    @Override
    public int getTransactionIsolation() throws SQLException {
    return isolationLevel;
    }

    @Override
    public SQLWarning getWarnings() throws SQLException {
    return null;
    }

    @Override
    public void clearWarnings() throws SQLException {

    }

    @Override
    public Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException {
    return new SSStatement( this, resultSetType, resultSetConcurrency);
    }

    @Override
    public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency) throws SQLException {
    return new SSPreparedStatement(this, sql, resultSetType, resultSetConcurrency);
    }

    @Override
    public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency) throws SQLException {
    return new SSCallableStatement(this, sql, resultSetType, resultSetConcurrency);
    }

    @Override
    public Map<String, Class<?>> getTypeMap() throws SQLException {
    return null;
    }

    @Override
    public void setTypeMap(Map<String, Class<?>> map) throws SQLException {

    }

    @Override
    public void setHoldability(int holdability) throws SQLException {
    this.holdability = holdability;
    }

    @Override
    public int getHoldability() throws SQLException {
    return holdability;
    }

    int getSavepoint() throws SQLException{
    testClosedConnection();
    return commitPages.size(); // the call is atomic, that it need not be synchronized
    }

    @Override
    public Savepoint setSavepoint() throws SQLException {
    return new SSSavepoint(getSavepoint(), null, transactionTime);;
    }

    @Override
    public Savepoint setSavepoint(String name) throws SQLException {
    return new SSSavepoint(getSavepoint(), name, transactionTime);
    }

    @Override
    public void rollback(Savepoint savepoint) throws SQLException {

    }

    @Override
    public void releaseSavepoint(Savepoint savepoint) throws SQLException {

    }

    @Override
    public Statement createStatement(int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException {
    return null;
    }

    @Override
    public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException {
    return null;
    }

    @Override
    public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException {
    return null;
    }

    @Override
    public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) throws SQLException {
    return null;
    }

    @Override
    public PreparedStatement prepareStatement(String sql, int[] columnIndexes) throws SQLException {
    return null;
    }

    @Override
    public PreparedStatement prepareStatement(String sql, String[] columnNames) throws SQLException {
    return null;
    }

    @Override
    public Clob createClob() throws SQLException {
    return null;
    }

    @Override
    public Blob createBlob() throws SQLException {
    return null;
    }

    @Override
    public NClob createNClob() throws SQLException {
    return null;
    }

    @Override
    public SQLXML createSQLXML() throws SQLException {
    return null;
    }

    @Override
    public boolean isValid(int timeout) throws SQLException {
    return false;
    }

    @Override
    public void setClientInfo(String name, String value) throws SQLClientInfoException {

    }

    @Override
    public void setClientInfo(Properties properties) throws SQLClientInfoException {

    }

    @Override
    public String getClientInfo(String name) throws SQLException {
    return null;
    }

    @Override
    public Properties getClientInfo() throws SQLException {
    return null;
    }

    public Array createArrayOf(String typeName, Object[] elements) throws SQLException {
    return null;
    }

    public Struct createStruct(String typeName, Object[] attributes) throws SQLException {
    return null;
    }

    public void setSchema(String schema) throws SQLException {

    }

    public String getSchema() throws SQLException {
    return null;
    }

    public void abort(Executor executor) throws SQLException {

    }

    public void setNetworkTimeout(Executor executor, int milliseconds) throws SQLException {

    }

    public int getNetworkTimeout() throws SQLException {
    return 0;
    }

    @Override
    public T unwrap(Class iface) throws SQLException {
    return null;
    }

    @Override
    public boolean isWrapperFor(Class<?> iface) throws SQLException {
    return false;
    }
    }

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值