jdbc连接数据库以及简单实现(普通JDBC方法实现和连接池方式实现)

@

总结内容

1. 基本概念

jdbc的概念

  • sun公司提供操作数据库的一套接口(规范、标准)。

2. 数据库连接

数据库的连接

  • 代码如下
// 贾琏欲执事(口诀)
// 定义一些需要使用的参数
String sql = "delete from Student where id = ? ";
String url = "jdbc:mysql://localhost:3306/db_test";
String username = "root";
String password = "admin";
// 加载数据库驱动(贾)
Class.forName("com.mysql.jdbc.Driver");
// 获取数据库连接(琏)
Connection conn = DriverManager.getConnection(url, username, password);
// 预编译sql语句(欲)
PreparedStatement ps = conn.prepareStatement(sql);
ps.setInt(1, id);
// 执行sql语句(执)
ps.executeUpdate();
// 释放资源(事)
statement.close();
conn.close();
  • 数据库CRUD(增删改查)操作
    1)在连接数据库之后我们需要根据需求对数据进行CRUD(增删改查)操作,一般我们会把CRUD操作放入DAO层中;

DAO层思想

  • DAO(Data Access Object)数据访问对象
    1)一个面向对象的数据库接口。也就是与数据库打交道,夹在业务逻辑与数据库资源中间,将所有对数据源的访问操作封装在一个公共API中。程序书写就是建立一个接口,接口中定义了此应用程序中将会用到的所有事务方法;

  • DAO中的主要操作
    1)增删改查(CRUD);

重构设计

  • 重构原因
    1)由于我们每次进行CRUD操作时都要创建数据库连接,以及释放资源等操作,这样会有大量冗余的代码,所以我们需要对重复操作的代码进行抽取;

  • 代码如下:

public class JDBCUtil {
    /**
     * @description: 使用单例模式建立工具类
    */
    private static JDBCUtil jdbc = new JDBCUtil();

    private JDBCUtil() {
    }

    public static JDBCUtil getInstance() {
        return jdbc;
    }

    static Properties p = null;
    static{
        p = new Properties();
        InputStream in = Thread.currentThread().getContextClassLoader().getResourceAsStream("jdbc.properties");
        try {
            p.load(in);
        } catch (IOException e) {
            e.printStackTrace();
        }
        try {
            Class.forName(p.getProperty("jdbc.driver"));
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

    /**
     * @description: 获取数据库连接
     */
    public Connection getCon() throws IOException, ClassNotFoundException, SQLException {
        return DriverManager.getConnection(p.getProperty("jdbc.url"), p.getProperty("jdbc.username"), p.getProperty("jdbc.password"));
    }

    /**
     * @description: 关闭资源
    */
    public void release(PreparedStatement ps, Connection conn, ResultSet rs) {
        // 释放资源
        if (ps != null) {
            try {
                ps.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if(conn != null) {
            try {
                conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if(rs != null) {
            try {
                rs.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }

    }
    // DML(增删改)操作的时候不需要使用ResultSet,只需要释放2个资源即可
    public void release(PreparedStatement ps, Connection conn) {
        // 重载调用前面的方法
        release(ps, conn, null);
    }
}

3. 事务

概念

  • 事务(Transaction,简写为tx)在数据库中,所谓事务是指一组逻辑操作单元,使数据从一种状态变换成另一种状态。

事务的ACID属性

  • 原子性(Atomicity)
    1)原子在化学中是最小单位,不可以再分割了。原子性是指事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生;

  • 一致性(Consistency)
    1)包装数据的完整性。事务必须使数据库从一个一致性状态转变成另一个一致性状态(数据不被破坏);
    2)例如:你从银行取钱,你取多少,你的账户就会被扣除多少,如果你账户余额不足,也就是取钱失败,账户余额会保持不变。数据库的数据一直处于一个一致性的状态,数据没有被破坏;

  • 隔离性(Isolation)
    1)事务的隔离性是指一个事务的执行不能被其他事务干扰,即一个事物内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰;

  • 持久性(Durability)
    1)持久性是指一个事务一旦被提交,它对数据库中数据的改变就是永久性的,接下来的其他操作和数据库故障不应该对其有任何影响。

事务的操作

  • 事务操作步骤
    1)先定义开始一个事务,然后对数据做修改操作;
    2)执行过程中,如果没有问题就提交(Commit)事务,此时的修改将永久的保存下来;
    3)如果执行过程中有问题(异常),回滚事务(rollback),数据库管理系统将放弃你开始事务后的所有修改而会带开始事务时的状态。

  • 事务操作模板

try {
  // 取消事务的自动提交机制,设置为手动提交
  connection对象.setAutoCommit(false);
  // 操作1
  // 操作2
  // ......
  
  // 手动提交事务
  connection对象.commit();
} catch(Exception e) {
  // 处理异常
  // 回滚事务
  connection对象.rollback();
}
  • 事务操作原理
    1)connection改为手动提交之后就被加锁了,必须使用commit()或者rollback()释放锁;
    2)rollback() 回滚并不是回滚数据,因为数据并没有提交,他的作用是释放connection的锁,让资源能够正常关闭。

4. 连接池

为什么要使用连接池

  • 普通JDBC连接数据库的缺点
    1)因为我们每次对数据库进行访问时都会先建立一个连接,访问后又会关闭该资源,而普通的JDBC数据库连接使用DriverManager获取,每次建立连接都要把COnnection加载到内存中,再验证用户名和密码(得话费0.05s~1s的时间),数据库的连接是比较昂贵的(创建的成本较大)。这样造成了资源和时间的大量浪费,所以我们使用连接池来连接数据库;
    2)每次建立连接都需要关闭,如果出现异常没能及时关闭会出现数据库系统的内存泄漏,导致数据库系统重启;
    3)每次建立连接又关闭的方式会让不能控制数据库的连接数,会导致系统资源被无限制的分配出去,如果连接过多也可能导致数据库内存泄漏,最终导致服务器崩溃。
  • 解决方案
    1)解决方案就是连接池的运用,在系统初始化的时候,主动去建立足够多的连接对象,组成一个连接池,使用的时候,我们只需要去连接池中取出,用完后不再是关闭连接,而是归还即可。

连接池分类

1)DBCP:Spring 框架推荐的;
2)Hibernate:Hibernate框架推荐的(已经被慢慢淘汰了);
3)Druid:阿里巴巴的连接池(号称Java语言中性能最好的连接池)。

使用连接池和不使用连接池的区别

  • 获取 Connection 对象
    1)没有使用连接池:Connection conn = DriverManager.getConnection(url,username,passwrod);
    2)使用了连接池:Connection conn = DataSource对象.getConnection();

  • 释放 Connection 对象
    1)没有使用连接池:直接和数据库服务器断开连接;
    2)使用了连接池:把 Connection 对象返回到连接池中,并没有与数据库服务器断开连接;

Druid连接池

Druid的使用

  • druid下载地址
    1)是阿里巴巴研发出来的号称Java语言领域性能最好的连接池;
    2)wiki地址:http://github.com/alibaba/druid/wiki

  • druid的使用
    1)使用与 DBCP 类似
    2)支持数据库 MySQL,Oracle,DB2,MS Server;
    3)支持对配置文件的密码加密。
    4)需要 jar:druid-版本号.jar

  • 数据库配置文件(db.properties)

// 这里的 key 必须要和 DruidDataSource 中对应的属性名一致
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/web_test02?characterEncoding=UTF-8&serverTimezone=GMT%2b8:00&useSSL=false
username=数据库的用户名
password=数据库密码
  • Druid工具类
    1)代码:
public class DruidUtil {
    /**
     * 创建单例模式
     */
    private DruidUtil() {
    }
    private static DruidUtil druidUtil = new DruidUtil();
    public static DruidUtil getInstance() {
        return druidUtil;
    }

    /**
     * 使用工厂类获取数据库连接池
     */
    static Properties ps = new Properties();
    static DataSource dataSource = null;
    static {
        try {
            ps.load(Thread.currentThread().getContextClassLoader().getResourceAsStream("db.properties"));
            dataSource = DruidDataSourceFactory.createDataSource(ps);
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    /**
     * 获取数据库连接
     */
    public Connection getCon() throws SQLException {
        return dataSource.getConnection();
    }

    /**
     * 释放资源
     */
    public void close(Connection conn, PreparedStatement ps, ResultSet rs) {
        if (rs != null) {
            try {
                rs.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if (ps != null) {
            try {
                ps.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if (conn != null) {
            try {
                conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
    public void close(Connection conn, PreparedStatement ps){
        close(conn, ps, null);
    }
}

2)调用

  // 获取连接对象
  Connection conn = DruidUtil.getInstance().getCon();

总结

以上就是 jdbc 连接数据库的总结了,代码仅供参考,欢迎讨论交流。

posted @ 2021-04-16 20:44  Yan_Yang  阅读(488)  评论(0编辑  收藏  举报