zoukankan      html  css  js  c++  java
  • java之JDBC

    一.JDBC基础

    1.1数据库驱动

    我们安装好数据库后,我们的应用程序是不能直接使用数据库的,需要通过相应的数据库驱动程序,然后通过驱动程序才可以和数据库沟通,即JAVA应用程序--ORACLE/MYSQL/SQL SERVER驱动--ORACLE/MYSQL/SQL SERVER数据库。

    1.2JDBC介绍

    Oracle-Sun公司为了简化和统一对数据库的操作,定义了一套java操作数据库的规范(接口),称为JDBC,然后各个数据库厂商按照这个规范(接口)去实现,然后,广大的开发人员只需要学习JDBC规范(接口),然后通过JDBC加载相应的驱动程序,就可以完成操作数据库的工作,即:JAVA应用程序--JDBC--ORACLE/MYSQL/SQL SERVER驱动--ORACLE/MYSQL/SQL SERVER数据库。

    在开发JDBC应用程序时需要用到两个包:java.sql和javax.sql,同时还需要导入相应的JDBC数据库驱动。

    1.3编写JDBC程序

    package com.boxiaoyuan.test;
    
    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    import java.sql.Statement;
    
    public class JdbcFirstDemo {
        public static void main(String[] args) {
            String url = "jdbc:mysql://localhost:3306/jdbcStudy";
            String username = "root";
            String password = "aaaaaa";
            Connection conn = null;
            Statement stmt = null;
            ResultSet rs = null;
            try {
                //1.加载驱动
                Class.forName("com.mysql.jdbc.Driver");//推荐使用这种方式来加载驱动
                //2.获取与数据库的连接
                conn = DriverManager.getConnection(url, username, password);    
                //3.获取用于向数据库发送sql语句的statement
                stmt = conn.createStatement();
                String sql = "select * from users";
                //4.向数据库发送sql,并获取结果集resultSet
                rs = stmt.executeQuery(sql);
                //5.获取结果集中的数据
                while (rs.next()) {
                    System.out.println("name:" + rs.getObject("name"));
                    
                }
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }catch (SQLException e) {
                e.printStackTrace();
            }finally {
                if(rs != null) {
                    try {
                        //6.关闭连接,释放资源
                        rs.close();
                    } catch (SQLException e) {
                        e.printStackTrace();
                    }
                }
                if(stmt != null) {
                    try {
                        //6.关闭连接,释放资源
                        stmt.close();
                    } catch (SQLException e) {
                        e.printStackTrace();
                    }
                }
                if(conn != null) {
                    try {
                        //6.关闭连接,释放资源
                        conn.close();
                    } catch (SQLException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }

    1.3.1DriverManager类

    JDBC程序中的DriverManager类用于加载驱动,并且创建与数据库的连接,这个API的常用方法为:DriverManager.getConnection(url, user, password)。

    在实际的开发过程中,加载驱动推荐的使用方式是Class.forName("com.mysql.jdbc.Driver");因为此方法不会导致驱动在内存中重复出现,灵活性很高。

    1.3.2数据库URL

    URL用于标识数据库的位置,通过URL可以让JDBC知道需要连接哪个数据库。

    常用的数据库URL地址写法:

    # sql server:jdbc:sqlserver://10.21.191.201:1433;DatabaseName=g1
    # postgresql
    jdbc:postgresql://10.21.191.201:5432/g1
    # oracle
    jdbc:oracle:thin:@//10.21.191.201:1521/g1
    # mysql
    jdbc:mysql://localhost:3306/jdbcStudy

     1.3.3Connection类

    JDBC程序中的Connection标识数据库的连接,Connection是数据库编程中最重要的一个对象,客户端与数据库服务器的交互都是通过Connection对象完成的,这个对象的常用方法有:

    1 createStatement()    创建一个静态sql语句对象
    2 prepareStatement(String sql)  创建预编译的sql语句对象
    3 prepareCall(String sql)   创建存储过程的sql语句对象

    1.3.4Statement类

    JDBC程序中的Statement对象用于向数据库发送SQL语句,这个对象的常用方法有:

    1 executeUpdate(String sql)  执行更新操作的sql语句,create/alter/drop/insert/update/delete)     
    2 executeQuery(String sql)  执行查询操作的sql语句(select)

    1.3.5ResultSet类

    JDBC程序中的ResultSet用于标识SQL语句的执行结果,ResultSet对象维护了一个指向表格数据行的游标,初始的时候,游标在第一行之前,调用.next()方法后,可以使游标指向具体的数据行,然后再调用方法获取改行的数据。

    获取任意类型的数据:

    1 getObject(int index)
    2 getObject(String columnName)

    获取指定类型的数据:

    1 getString(int index)
    2 getString(String columnName)

    另外,ResultSet还提供了对结果集进行滚动的方法:

    1 next():移动到下一行
    2 Previous():移动到前一行
    3 absolute(int row):移动到指定行
    4 beforeFirst():移动到ResultSet的最前面
    5 afterLast():移动到Result的最后面

    1.3.6释放资源

    JDBC程序运行后,一定要释放程序运行中创建的与数据库进行交互的对象,这些对象通常为ResultSet,Statement,Connection,特别是Connection,如果该对象用完之后不能及时释放,很容易导致宕机的发生。为了确保资源释放代码能够运行,资源释放代码一定要放在finally语句中。

     二.使用JDBC对数据库进行增删改查

    JDBC中的Statement对象用于向数据库发送SQL语句,如果想要完成对数据库的增删改查,只需要通过这个对象发送增删改查即可。其中该对象的executeUpdate方法,用于向数据库发送增,删,改语句,该方法执行完之后,会返回一个整数表示数据库中多少行数据发生了变化;该对象的executeQuery方法,用于向数据库中发送查询语句,该方法返回ResultSet对象,表示查询结果。

    2.1准备

    首先在src目录下新增加一个配置文件,db.properties,然后在里面维护Mysql数据库的连接信息:

    driver=com.mysql.jdbc.Driver
    url=jdbc:mysql://localhost:3306/jdbcStudy
    username=root
    password=aaaaaa

    2.2编写JdbcUtils工具类

    编写JdbcUtils工具类,用来连接数据库,获取数据库连接释放数据库连接:

    package com.boxiaoyuan.www;
    
    import java.io.InputStream;
    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    import java.sql.Statement;
    import java.util.Properties;
    
    public class JdbcUtils {
        private static String driver = null;
        private static String url = null;
        private static String username = null;
        private static String password = null;
        static {        
            try {
                InputStream inStream = JdbcUtils.class.getClassLoader().getResourceAsStream("db.properties");
                Properties prop = new Properties();
                prop.load(inStream);
                //获取连接数据库的url地址
                url = prop.getProperty("url");
                //获取数据库连接驱动
                driver = prop.getProperty("driver");
                //获取数据库连接用户名
                username = prop.getProperty("username");
                //获取数据库连接密码
                password = prop.getProperty("password");
                //加载数据库驱动
                Class.forName(driver);
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        
        public static Connection getConnection() throws SQLException {
            return DriverManager.getConnection(url, username, password);
        }
        
        public static void release(Connection conn, Statement stmt, ResultSet rs) {
            if(rs != null) {
                try {
                    //关闭结果集对象ResultSet
                    rs.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }finally {
                    rs = null;
                }    
            }
            if(stmt != null) {
                try {
                    //关闭执行SQL的对象Statement
                    stmt.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }finally {
                    stmt = null;
                }
            }
            if(conn != null) {
                try {
                    //关闭数据库连接对象Connection
                    conn.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }finally {
                    conn = null;
                }
            }
        }
    }

    2.3使用Statement对象增删改查

    package com.boxiaoyuan.www;
    
    import java.sql.Connection;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    import java.sql.Statement;
    
    import org.junit.Test;
    
    public class Demo01 {
        @Test
        public void insert() {
            Connection conn = null;
            Statement stmt = null;
            ResultSet rs = null;
            try {
                conn = JdbcUtils.getConnection();
                stmt = conn.createStatement();
                String sql = "insert into users(id,name,password,email,birthday) values(12,'boxiaoyuan', '111111', 'test@qq.com', '1990-01-01')";
                int num = stmt.executeUpdate(sql);
                if(num>0) {
                    System.out.println("插入成功");
                }
                
            } catch (SQLException e) {
                e.printStackTrace();
            }finally {
                JdbcUtils.release(conn, stmt, rs);
            }
        }
        @Test
        public void delete() {
            Connection conn  = null;
            Statement stmt = null;
            ResultSet rs = null;
            try {
                conn = JdbcUtils.getConnection();
                stmt = conn.createStatement();
                String sql = "delete from users where id='12'";
                int num = stmt.executeUpdate(sql);
                if(num>0) {
                    System.out.println("删除成功");
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }finally {
                JdbcUtils.release(conn, stmt, rs);
            }    
        }
        @Test
        public void update() {
            Connection conn = null;
            Statement stmt = null;
            ResultSet rs = null;
            try {
                conn = JdbcUtils.getConnection();
                stmt = conn.createStatement();
                String sql = "update users set password='222222' where id='12'";
                int num = stmt.executeUpdate(sql);
                if(num>0) {
                    System.out.println("修改成功");
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }finally {
                JdbcUtils.release(conn, stmt, rs);
            }
        }
        @Test
        public void query() {
            Connection conn = null;
            Statement stmt = null;
            ResultSet rs = null;
            try {
                conn = JdbcUtils.getConnection();
                stmt = conn.createStatement();
                String sql = "select * from users";
                rs = stmt.executeQuery(sql);
                while(rs.next()) {
                    System.out.println(rs.getObject("name")+"----"+rs.getObject("password"));
                }
            } catch (SQLException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }finally {
                JdbcUtils.release(conn, stmt, rs);
            }    
        }
    }

    3.PreparedStatement对象介绍

    PreparedStatement是Statement的子类,它的实例可以通过Connection.preparedStatement方法获得,与Statement对象比较,PreparedStatement可以避免SQL注入。

    Statement会使数据库频繁的编译SQL,可能会造成数据库缓冲器溢出,但是PreparedStatement可以对SQL进行预编译,从而提高了数据库的执行效率。

    3.1使用PreparedStatement对象增删改查

    package com.boxiaoyuan.www;
    
    import java.sql.Connection;
    import java.sql.Date;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    
    import org.junit.Test;
    
    
    public class Demo01 {
        @Test
        public void insert() {
            Connection conn = null;
            PreparedStatement stmt = null;
            ResultSet rs = null;
            try {
                conn = JdbcUtils.getConnection();
                String sql = "insert into users(id,name,password,email,birthday) values(?,?,?,?,?)";
                stmt = conn.prepareStatement(sql);
                stmt.setInt(1, 13);
                stmt.setString(2, "bodayuan");
                stmt.setString(3, "aaaaaa");
                stmt.setString(4, "aa@sina.com");
                stmt.setDate(5, new Date(new java.util.Date().getTime()));
                int num = stmt.executeUpdate();
                if(num>0) {
                    System.out.println("插入成功");
                }
                
            } catch (SQLException e) {
                e.printStackTrace();
            }finally {
                JdbcUtils.release(conn, stmt, rs);
            }
        }
        @Test
        public void delete() {
            Connection conn  = null;
            PreparedStatement stmt = null;
            ResultSet rs = null;
            try {
                conn = JdbcUtils.getConnection();
                String sql = "delete from users where id=?";
                stmt = conn.prepareStatement(sql);
                stmt.setInt(1, 13);
                int num = stmt.executeUpdate();
                if(num>0) {
                    System.out.println("删除成功");
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }finally {
                JdbcUtils.release(conn, stmt, rs);
            }    
        }
        @Test
        public void update() {
            Connection conn = null;
            PreparedStatement stmt = null;
            ResultSet rs = null;
            try {
                conn = JdbcUtils.getConnection();
                String sql = "update users set password=? where id=?";
                stmt = conn.prepareStatement(sql);
                stmt.setString(1, "bbbbbb");
                stmt.setInt(2, 13);
                int num = stmt.executeUpdate();
                if(num>0) {
                    System.out.println("修改成功");
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }finally {
                JdbcUtils.release(conn, stmt, rs);
            }
        }
        @Test
        public void query() {
            Connection conn = null;
            PreparedStatement stmt = null;
            ResultSet rs = null;
            try {
                conn = JdbcUtils.getConnection();
                String sql = "select * from users where id=?";
                stmt = conn.prepareStatement(sql);
                stmt.setInt(1, 13);
                rs = stmt.executeQuery();
                while(rs.next()) {
                    System.out.println(rs.getObject("name")+"----"+rs.getObject("password"));
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }finally {
                JdbcUtils.release(conn, stmt, rs);
            }    
        }
    }

     4.事务

    4.1事务的概念

    事务是指逻辑上的一组操作,组成这组操作的各个单元,要么全部成功,要么全部不成功。

    4.2JDBC中使用事务

    当JDBC程序向数据库获得一个Connection对象时,默认这个Connection对象会自动向数据库提交发送的SQL语句,如果想要关闭这种默认的提交方式,让多条SQL在一个事务中执行,可以使用如下的语句控制:

    Connection.setAutoCommit(false);//开启事务
    Connection.rollback();//回滚事务
    Connection.commit();//提交事务

    4.3示例

    下面模拟银行转账的业务,用户A转账给用户B,用户B接收用户A的转账。

    update account set money=money-10000 where name='A';
    update account set money=money+10000 where name='B';
    package com.boxiaoyuan.www;
    
    import java.sql.Connection;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    
    import org.junit.Test;
    
    
    
    public class Demo02 {
        /**
         * 模拟转账成功的场景
         */
        @Test
        public void transantion1() {
            Connection conn = null;
            PreparedStatement stmt = null;
            ResultSet rs = null;
            try {
                conn = JdbcUtils.getConnection();
                conn.setAutoCommit(false);//通知数据库开启事务
                String sql = "update account set money=money-10000 where name='A'";
                stmt = conn.prepareStatement(sql);
                stmt.executeUpdate();
                String sql2 = "update account set money=money+10000 where name='B'";
                stmt = conn.prepareStatement(sql2);
                stmt.executeUpdate();
                conn.commit();//执行完上面两条语句后,提交事务
                System.out.println("执行成功");
            } catch (SQLException e) {
                e.printStackTrace();
            }finally {
                JdbcUtils.release(conn, stmt, rs);
            }
        }
        /**
         * 模拟转账过程中出现异常,程序自动回滚
         */
        @Test
        public void testTransaction2() {
            Connection conn = null;
            PreparedStatement stmt = null;
            ResultSet rs = null;
            try {
                conn = JdbcUtils.getConnection();
                conn.setAutoCommit(false);//告诉数据库开始事务
                String sql = "update account set money=money-10000 where name='A'";
                stmt = conn.prepareStatement(sql);
                stmt.executeUpdate();
                int m = 2/0;//程序出错,导致后续的程序无法进行,事务无法正常提交,数据库自动回滚
                String sql2 = "update account set money=money+10000 where name='B'";
                stmt = conn.prepareStatement(sql2);
                stmt.executeUpdate();
                conn.commit();//提交事务
                System.out.println("执行成功");
            } catch (SQLException e) {
                e.printStackTrace();
            }finally {
                JdbcUtils.release(conn, stmt, rs);
            }
        }
        /**
         * 模拟转账过程中出现异常,手动回滚事务
         */
        @Test
        public void testTransaction3() {
            Connection conn = null;
            PreparedStatement stmt = null;
            ResultSet rs = null;
            try {
                conn = JdbcUtils.getConnection();
                conn.setAutoCommit(false);//告诉数据库开始事务
                String sql = "update account set money=money-10000 where name='A'";
                stmt = conn.prepareStatement(sql);
                stmt.executeUpdate();
                int m = 2/0;//程序出错
                String sql2 = "update account set money=money+10000 where name='B'";
                stmt = conn.prepareStatement(sql2);
                stmt.executeUpdate();
                conn.commit();//提交事务
                System.out.println("执行成功");
            } catch (SQLException e) {
                try {
                    conn.rollback();//捕获异常后手动执行数据库回滚操作
                } catch (SQLException e1) {
                    e1.printStackTrace();
                }
                e.printStackTrace();
            }finally {
                JdbcUtils.release(conn, stmt, rs);
            }
        }
    }
  • 相关阅读:
    修改数据库的兼容级别
    如何写出安全的API接口
    最新IP地址数据库
    java 中的静态(static)代码块
    Java RTTI(类型信息)(.class 类对象)
    机器学习之决策树预测——泰坦尼克号乘客数据实例
    敏捷开发 —— TDD(测试驱动开发)
    Java 内存泄漏
    红顶商人 —— 胡雪岩
    各地特色美食与点菜的艺术
  • 原文地址:https://www.cnblogs.com/zhuzhaoli/p/10747535.html
Copyright © 2011-2022 走看看