`

数据库 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> T unwrap(Class<T> iface) throws SQLException {
        return null;
    }

    @Override
    public boolean isWrapperFor(Class<?> iface) throws SQLException {
        return false;
    }
}
0
1
分享到:
评论

相关推荐

    DBCP( Database Connection Pool )数据库连接池

    连接池本质上就是一个容器,用来存储、管理和维护数据库连接,而不是每次都新建或断开连接。 #### 三、DBCP的使用 ##### 1. 导入JAR包 使用DBCP的第一步是在项目中导入必要的JAR包。通常需要两个JAR包: - `...

    在C#中删除数据库

    在C#中删除数据库涉及到对SQL Server或者其它支持的数据库系统的操作,这通常需要通过ADO.NET库或者其他数据访问技术来实现。以下是一个详尽的步骤和知识点解释: 1. **数据库连接**: 首先,你需要创建一个数据库...

    VB的DATA数据格式链接数据库

    例如,使用`ADODB.Connection`对象建立到数据库的连接,`ADODB.Recordset`对象用于操作数据。以下是一般步骤: 1. 建立连接:使用`ConnectionString`属性设置数据库连接字符串,并用`Connection.Open`打开连接。 2. ...

    利用ASP技术实现对数据库的操作

    ### 利用ASP技术实现对数据库的操作 #### 一、引言 随着互联网技术的发展,动态网页成为构建交互式Web应用的重要方式之一。ASP(Active Server Pages)是一种用于开发动态网页的技术,它允许开发者轻松地将HTML...

    图片保存到数据库

    在IT领域,将图片保存到数据库是一个常见的需求,尤其是在Web应用和移动应用中,为了方便管理和访问,开发者经常需要将用户的头像、产品图片、证书等图像数据存储在数据库中。这一过程涉及到图像的编码、解码以及...

    通过excel上传数据到数据库

    Excel文件本质上是XML格式,但通常以.xlsx或.xls为扩展名。新版本的Excel(.xlsx)采用Open XML标准,这是一个基于ZIP的压缩格式,包含多个XML文件,分别对应工作表、样式、公式等内容。而旧版的.xls文件则使用二...

    PHP-PDO数据库操作类

    使用PDO数据库操作类,虽然在设计上遵循面向对象编程原则,但也可以满足过程编程爱好者的需求,因为类中的方法本质上就是封装的过程,可以通过实例化类并调用方法来实现数据库操作。 6. **标签解析** - **PDO**:...

    使用数据库连接组件打开EXCEL

    Excel文件虽然本质上是非关系型的,但通过特定的连接方式,我们可以将其视为一个临时的数据库来处理。以下是关于这个主题的详细说明: 1. **数据库连接组件**:常见的数据库连接组件包括JDBC(Java Database ...

    jsp项目与数据库连接测试

    【jsp项目与数据库连接测试】是一个基础的Web开发实践,主要目标是验证JavaServer Pages (JSP)技术能否成功地与MySQL数据库进行交互。在这个项目中,开发者通常会创建一个JSP页面,通过该页面来执行数据库查询或更新...

    JSP中连接SQL Server2005数据库

    2. **创建连接**:使用`DriverManager.getConnection()`方法创建数据库连接。 ```java Connection conn = DriverManager.getConnection(url, username, password); ``` 3. **预编译SQL语句(可选)**:如果执行...

    基于ADO.NET技术访问Oracle数据库的实现.pdf

    ADO.NET本质上是一个类库集,是.NET编程环境中的优先数据库访问接口。 三、ADO.NET体系结构 ADO.NET数据访问技术主要核心组件有两个,即数据集(DataSet)和数据提供程序(.NET Framework Data Provider)。 (1...

    二进制图片上传到数据库

    所有计算机数据本质上都是二进制的,由0和1组成。图片文件是一种二进制数据的组织形式,包含图像像素的颜色值和结构信息。在处理图片时,我们可以使用编程语言如Python的PIL(Python Imaging Library)或Java的...

    C#将网络上的图片直接下载到数据库

    图片本质上是二进制数据,因此在存储到数据库之前,我们需要将图片文件的字节内容进行处理。在C#中,我们可以使用`FileStream`读取本地文件,或者直接操作`byte[]`数组。对于数据库操作,通常使用ADO.NET接口,如`...

    数据库连接JDBC详解

    要建立与数据库的连接,可以通过调用 `DriverManager.getConnection(String url, String user, String password)` 方法来完成。这个方法会根据提供的 URL 查找合适且已注册的 Driver 对象,并由 Driver 创建相应的 `...

    VC数据库编程

    在VC++环境中进行数据库编程是一项基础且重要的技能,...通过深入学习和实践“VC数据库编程”,初学者不仅能掌握如何在VC++环境中使用数据库,还能了解到数据库系统的本质和优化方法,为今后的软件开发奠定坚实基础。

    数据库面试题总结

    存储过程和函数都是数据库中预编译的代码段,但它们之间存在本质区别。存储过程是一系列SQL语句的集合,通常用于执行复杂的数据库操作,如数据插入、更新、删除等,它们可以包含控制流语句,如循环、条件判断等,且...

    JSP数据库编程指南

    首先,需要加载数据库驱动,然后通过`DriverManager.getConnection()`方法建立连接。例如: ```java Class.forName("com.mysql.jdbc.Driver"); Connection conn = DriverManager.getConnection("jdbc:mysql://...

    JDBC连接Oracle和SQL Server数据库探析.pdf

    这种方式实质上是利用纯Java语言编写的Oracle数据库访问接口,因此,它在不需要安装额外软件的情况下即可完成数据库的连接。thin方式的操作步骤包括下载Oracle JDBC驱动、配置驱动文件路径以及通过thin方式获取...

Global site tag (gtag.js) - Google Analytics