zoukankan      html  css  js  c++  java
  • 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();
        }
    }
  • 相关阅读:
    论语心得
    水果总结
    欢乐颂
    大牌驾到
    Excel补全日期(日期按顺序补全)
    c语言define和typedef区别和使用
    c语言寄存器变量
    c语言伪常量const理解
    c语言静态断言-定义自己的静态断言
    c语言静态断言
  • 原文地址:https://www.cnblogs.com/sniffs/p/13485254.html
Copyright © 2011-2022 走看看