JDBC编程

JDBC简介

JDBC,Java DataBase Connectivity,是java提供的访问数据库的标准接口;不同的数据库厂商实现了该接口类作为数据库驱动,比如MySql提供的驱动jar包为mysql-connector-java;

java提供了如下几个重要的接口类:

1、Connection接口

提供了java应用程序到数据库的TCP连接;

2、Statement接口

提供数据库操作接口,executeQuery用于执行查询操作;executeUpdate用来执行insert、update、delete、DDL(删除表等)操作;execute方法可以用于执行任何操作

3、PreparedStatement接口

提供数据库操作接口,不同的是,PreparedStatement预编译sql语句,提升了执行效率,并且对于输入参数使用占位符,防止了SQL注入的发生;

注:java应用程序中永远不要使用Statement接口

4、CallableStatement接口

支持执行存储过程接口

JDBC查询操作

public void test_query() {
    try (Connection connection = DriverManager.getConnection(URL, USER, PASSWORD);
         PreparedStatement preparedStatement = connection.prepareStatement(QUERY_SQL)) {
        preparedStatement.setString(1, "bale");
        ResultSet resultSet = preparedStatement.executeQuery();
        while (resultSet.next()) {
            String name = resultSet.getString(1);
            int age = resultSet.getInt(2);
            int sex = resultSet.getInt(3);
            System.out.println("name=" + name + ", age=" + age + ", sex=" + sex);
        }
    } catch (SQLException ex) {
        ex.printStackTrace();
    }
}

注:Connection和Statement是系统资源,使用完成后需要释放,这里使用try with resource语法糖进行释放;

JDBC更新操作

public void test_update() {
    try (Connection connection = DriverManager.getConnection(URL, USER, PASSWORD);
         PreparedStatement preparedStatement = connection.prepareStatement(INSERT_SQL, Statement.RETURN_GENERATED_KEYS)) {
        preparedStatement.setString(1, "ramos");
        preparedStatement.setInt(2,32);
        preparedStatement.setInt(3, 2);
        int i = preparedStatement.executeUpdate();
        System.out.println("afftected rows: " + i);
        ResultSet generatedKeys = preparedStatement.getGeneratedKeys();
        while (generatedKeys.next()) {
            long aLong = generatedKeys.getLong(1);
            System.out.println(aLong);
        }
    } catch (SQLException ex) {
        ex.printStackTrace();
    }
}

注:executeUpdate可以执行insert、update、delete、以及数据库自带的DDL操作;可以在预编译sql时指定返回自增键值;

JDBC事务

数据库事务即一个或者一系列数据库操作,这些操作要么全部执行成功,要么全部不执行;类似于java中的多线程,数据库事务可以并发执行,与之带来的就是一系列并发问题:

1、脏读问题

事务A读取到了事务B未提交的数据,当事务B回滚时,事务A即读到了脏数据;

2、不可重复读问题

事务A多次读取数据,在多次的中间,事务B修改了数据,导致了事务A多次读取数据结果不同;

3、幻读问题

事务A多次读取数据,在多次的中间,事务B向数据库中插入了数据,导致事务A多次读取结果不同;和不可重复读的区别是:幻读强调的是表中数据条数的不同,而不可重复读强调的是某条数据发生变化,也就是说解决幻读问题需要锁表,而解决不可重复读问题只需要锁某条数据即可

针对事务并发带来的问题,数据库提供了事务隔离级别:mysql默认的事务隔离级别为read commit

  脏读 不可重复读 幻读
read uncommit 存在 存在 存在
read commit   存在 存在
repeatable read     存在
serializable      

 

 

 

 

 

 

 

默认情况下,一条操作即为一个事务,并且事务是自动提交的;可以通过connection.setAutoCommit(false)来取消自动提交,并且在执行数据库操作后通过connection.commit提交事务;

JDBC批次操作

对于多个操作相同,数据不同的数据操作,我们可以使用for循环来多次执行,但是这样效率很低;对于该场景,JDBC提供了batch操作,对于batch操作,整体的效率比for循环多次执行高的多

public void test_batch() {
    try (Connection connection = DriverManager.getConnection(URL, USER, PASSWORD);
         PreparedStatement preparedStatement = connection.prepareStatement(INSERT_SQL)) {

        for (int i = 0; i < 3; i++) {
            preparedStatement.setString(1, "ramos" + i);
            preparedStatement.setInt(2,32 + i);
            preparedStatement.setInt(3, 2 + i);
            preparedStatement.addBatch();
        }
        preparedStatement.executeBatch();
    } catch (SQLException ex) {
        ex.printStackTrace();
    }
}

JDBC连接池

和多线程类似,数据库连接的不断创建和销毁会带来很大的系统资源消耗,和线程池类似,java提供了标准的数据库连接池接口DataSource,而DataSource接口的实现类即为我们常说的数据源,常用的数据源有:c3p0数据源、druid数据源;

数据库连接通过dataSource获取,第一次获取时,创建连接;之后的获取先判断连接池中是否有空闲的连接,如果没有则创建,直到最大连接数;

而java程序中对connection的close方法调用不会真正释放连接,而是将连接标识为空闲状态

public void test_datasource() throws PropertyVetoException {
    ComboPooledDataSource dataSource = new ComboPooledDataSource();
    dataSource.setDriverClass("com.mysql.cj.jdbc.Driver");
    dataSource.setJdbcUrl(URL);
    dataSource.setUser(USER);
    dataSource.setPassword(PASSWORD);

    try (Connection connection = dataSource.getConnection();
         PreparedStatement preparedStatement = connection.prepareStatement(QUERY_SQL)) {

        preparedStatement.setString(1, "bale");
        final ResultSet resultSet = preparedStatement.executeQuery();
        while (resultSet.next()) {
            String name = resultSet.getString(1);
            int age = resultSet.getInt(2);
            int sex = resultSet.getInt(3);
            System.out.println("name=" + name + ", age=" + age + ", sex=" + sex);
        }
    } catch (SQLException ex) {
        ex.printStackTrace();
    }
}
posted @ 2020-08-11 21:26  光头用沙宣  阅读(118)  评论(0编辑  收藏  举报