zoukankan      html  css  js  c++  java
  • Unit02: JDBC核心API

        Unit02: JDBC核心API    

    db.properties

    注意:如果使用连接池,可以在这个文件中增加对连接池的相关设置:

    连接池参数,常用参数有:

    • 初始连接数
    • 最大连接数
    • 最小连接数
    • 每次增加的连接数
    • 超时时间
    • 最大空闲连接
    • 最小空闲连接
    # db connection parameters
    # key=value
    driver=oracle.jdbc.driver.OracleDriver
    url=jdbc:oracle:thin:@192.168.201.227:1521:orcl
    user=openlab
    pwd=open123
    # datasource parameters
    initSize=1
    maxSize=1

    DBUtil.java

    说明:DBUtil是DBTool的升级版,采用了连接池来管理连接。

    package util;
    
    import java.io.IOException;
    import java.sql.Connection;
    import java.sql.SQLException;
    import java.util.Properties;
    
    import org.apache.commons.dbcp.BasicDataSource;
    
    /**
     *    1.DBUtil是DBTool的升级版
     *    2.采用了连接池来管理连接
     */
    public class DBUtil {
        
        //DBCP连接池提供的实现类
        private static BasicDataSource ds;
        
        static {
            Properties p = new Properties();
            try {
                //1.读取参数
                p.load(DBUtil.class.getClassLoader()
                    .getResourceAsStream("db.properties"));
                String driver = p.getProperty("driver");
                String url = p.getProperty("url");
                String user = p.getProperty("user");
                String pwd = p.getProperty("pwd");
                String initSize = p.getProperty("initSize");
                String maxSize = p.getProperty("maxSize");
                //2.创建连接池(1次)
                ds = new BasicDataSource();
                //3.向连接池设置参数
                ds.setDriverClassName(driver);
                ds.setUrl(url);
                ds.setUsername(user);
                ds.setPassword(pwd);
                ds.setInitialSize(new Integer(initSize));
                ds.setMaxActive(new Integer(maxSize));
            } catch (IOException e) {
                //异常的处理原则:
                //1.记录日志(Log4j)
                e.printStackTrace();
                //2.能解决就解决(看开发规范)
                //3.解决不了向上抛给调用者
                //具体抛出哪种类型的异常看开发规范
                throw new RuntimeException(
                    "加载配置文件失败", e);
            }
        }
        
        public static Connection getConnection() 
            throws SQLException {
            return ds.getConnection();
        }
        
        /**
         * 1.目前我们使用连接都是连接池创建的
         * 2.连接池重写了连接对象内部的close()
         * 3.目前close()内部的逻辑是归还:
         *      - 清除连接对象内部包含的所有数据
         *      - 将连接对象状态设置为空闲态
         */
        public static void close(Connection conn) {
            if(conn != null) {
                try {
                    conn.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                    throw new RuntimeException(
                        "关闭连接失败", e);
                }
            }
        }
    
    }

    Test.java

    说明:这个类用于测试DBUtil

    package jdbc;
    
    import java.sql.Connection;
    import java.sql.Date;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    import java.sql.Statement;
    
    import org.junit.Test;
    
    import util.DBUtil;
    
    public class TestDay02 {
        
        /**
         * 1.测试DBUtil
         * 2.执行DQL
         *     查询部门ID为1的员工
         */
        @Test
        public void test1() {
            //假设页面传入的查询条件是
            int deptno = 1;
            
            Connection conn = null;
            try {
                conn = DBUtil.getConnection();
                System.out.println(conn);
                Statement smt = conn.createStatement();
                String sql = 
                    "select * from emps_lhh "
                    + "where deptno="+deptno;
                ResultSet rs = smt.executeQuery(sql);
                while(rs.next()) {
                    System.out.println(rs.getInt("empno"));
                    System.out.println(rs.getString("ename"));
                }
            } catch (SQLException e) {
                e.printStackTrace();
                //测试代码可以适当简化异常处理
            } finally {
                DBUtil.close(conn);
            }
        }
    
        /**
         * 演示如何使用PS执行DML
         */
        @Test
        public void test2() {
            //假设页面传入的数据是
            String ename = "曹操";
            String job = "丞相";
            int mgr = 0;
            Date hiredate = 
                Date.valueOf("2017-01-22");
            Double sal = 8000.0;
            Double comm = 9000.0;
            int deptno = 3;
            
            Connection conn = null;
            try {
                conn = DBUtil.getConnection();
                //写sql时条件用?代替
                String sql = 
                    "insert into emps_lhh values("
                    + "emps_seq_lhh.nextval,"
                    + "?,?,?,?,?,?,?)";
                //创建PS并传入sql,PS会立刻发送此sql
                PreparedStatement ps = 
                    conn.prepareStatement(sql);
                //先设置条件:给?赋值
                //ps.set类型(?的序号,?的值)
                ps.setString(1, ename);
                ps.setString(2, job);
                ps.setInt(3, mgr);
                ps.setDate(4, hiredate);
                ps.setDouble(5, sal);
                ps.setDouble(6, comm);
                ps.setInt(7, deptno);
                //发送参数,执行SQL(计划)
                ps.executeUpdate();
            } catch (SQLException e) {
                e.printStackTrace();
            } finally {
                DBUtil.close(conn);
            }
        }
        
        /**
         * 演示如何使用PS执行DQL
         */
        @Test
        public void test3() {
            //假设页面传入的查询条件是
            int empno = 1;
            
            Connection conn = null;
            try {
                conn = DBUtil.getConnection();
                String sql = 
                    "select * from emps_lhh "
                    + "where empno=?";
                PreparedStatement ps = 
                    conn.prepareStatement(sql);
                ps.setInt(1, empno);
                ResultSet rs = ps.executeQuery();
                if(rs.next()) {
                    System.out.println(rs.getString("ename"));
                    System.out.println(rs.getString("job"));
                }
            } catch (SQLException e) {
                e.printStackTrace();
            } finally {
                DBUtil.close(conn);
            }
            
        }
        
        /**
         * 使用PS执行查询语句,可以避免注入攻击
         */
        @Test
        public void test4() {
            //假设页面传入的参数是
            String user = "zhangsan";
            String pwd = "a' or 'b'='b";
            
            Connection conn = null;
            try {
                conn = DBUtil.getConnection();
                String sql = 
                    "select * from users_lhh "
                    + "where username=? "
                    + "and password=?";
                PreparedStatement ps = 
                    conn.prepareStatement(sql);
                ps.setString(1, user);
                ps.setString(2, pwd);
                ResultSet rs = ps.executeQuery();
                if(rs.next()) {
                    System.out.println("登录成功");
                } else {
                    System.out.println("账号或密码错误");
                }
            } catch (SQLException e) {
                e.printStackTrace();
            } finally {
                DBUtil.close(conn);
            }
        }
    
    }

     Test.java

    1. 演示如何从ResultSetMetaData中读取结果集相关的描述信息.
    2. 模拟转账业务.
    3. 批量添加员工(共108个,每批加50个)
    4. 添加部门及员工数据,添加员工时需要获取到部门的ID
    package jdbc;
    
    import java.sql.Connection;
    import java.sql.Date;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.sql.ResultSetMetaData;
    import java.sql.SQLException;
    
    import org.junit.Test;
    
    import util.DBUtil;
    
    public class TestDay03 {
    
        /**
         * 演示如何从ResultSetMetaData
         * 中读取结果集相关的描述信息.
         */
        @Test
        public void test1() {
            //假设页面传入的查询条件是
            int empno = 1;
            
            Connection conn = null;
            try {
                conn = DBUtil.getConnection();
                String sql = 
                    "select * from emps_lhh "
                    + "where empno=?";
                PreparedStatement ps = 
                    conn.prepareStatement(sql);
                ps.setInt(1, empno);
                ResultSet rs = ps.executeQuery();
                //获取结果集元数据,它是一个对象,
                //内部封装了对结果集的描述信息.
                ResultSetMetaData md = rs.getMetaData();
                //多少列
                System.out.println(md.getColumnCount());
                //第1列的列名
                System.out.println(md.getColumnName(1));
                //第1列的类型的编号(常量)
                System.out.println(md.getColumnType(1));
                //第1列的类型的名称
                System.out.println(md.getColumnTypeName(1));
            } catch (SQLException e) {
                e.printStackTrace();
            } finally {
                DBUtil.close(conn);
            }
        }
    
        /**
         * 模拟转账业务.
         * 
         * 假设此时用户已经登录了网银,
         * 并且已经输入了收款方账号和
         * 转账的金额,点击了转账.
         * 
         * 转账的步骤:
         * 1.验证收款方账号是否存在(查询)
         * 2.验证付款方余额是否够用(查询)
         * 3.将付款方余额-N元(修改)
         * 4.将收款方余额+N元(修改)
         */
        @Test
        public void test2() {
            //假设用户输入的信息如下
            //付款方账号
            String payId = "00001";
            //收款方账号
            String recId = "00002";
            //转账的金额
            double mny = 1000.0;
            
            //转账是一个完整的业务流程,必须保证
            //它的完整性,即该流程应处于一个事务
            //之内,所以创建一个连接.
            Connection conn = null;
            try {
                conn = DBUtil.getConnection();
                //取消自动提交事务
                conn.setAutoCommit(false);
                //1.查询收款方账号并验证
                String sql = 
                    "select * from accounts_lhh "
                    + "where id=?";
                PreparedStatement ps = 
                    conn.prepareStatement(sql);
                ps.setString(1, recId);
                ResultSet rs = ps.executeQuery();
                if(!rs.next()) {
                    throw new SQLException("收款方账号不存在");
                }
                double recMny = rs.getDouble("money");
                //2.查询付款方余额并验证
                String sql2 = 
                    "select * from accounts_lhh "
                    + "where id=?";
                PreparedStatement ps2 = 
                    conn.prepareStatement(sql2);
                ps2.setString(1, payId);
                ResultSet rs2 = ps2.executeQuery();
                double payMny = 0.0;
                if(rs2.next()) {
                    payMny = rs2.getDouble("money");
                    if(payMny<mny) {
                        throw new SQLException("余额不足");
                    }
                }
                //3.修改付款方余额
                String sql3 = 
                    "update accounts_lhh set "
                    + "money=? where id=?";
                PreparedStatement ps3 = 
                    conn.prepareStatement(sql3);
                ps3.setDouble(1, payMny-mny);
                ps3.setString(2, payId);
                ps3.executeUpdate();
                
                Integer.valueOf("断电了");
                
                //4.修改收款方余额
                String sql4 =
                    "update accounts_lhh set "
                    + "money=? where id=?";
                PreparedStatement ps4 = 
                    conn.prepareStatement(sql4);
                ps4.setDouble(1, recMny+mny);
                ps4.setString(2, recId);
                ps4.executeUpdate();
                
                //转账是一个完整的过程,只需要在
                //整个流程完成后,提交一次事务即可.
                conn.commit();
            } catch (Exception e) {
                e.printStackTrace();
                try {
                    conn.rollback();
                } catch (SQLException e1) {
                    e1.printStackTrace();
                }
            } finally {
                DBUtil.close(conn);
            }
        }
        
        /**
         *    批量添加员工(共108个,每批加50个)
         */
        @Test
        public void test3() {
            //这是一个完整的业务,只创建
            //1个连接,提交1次事务
            Connection conn = null;
            try {
                conn = DBUtil.getConnection();
                conn.setAutoCommit(false);
                String sql = 
                    "insert into emps_lhh values("
                    + "emps_seq_lhh.nextval,"
                    + "?,?,?,?,?,?,?)";
                PreparedStatement ps = 
                    conn.prepareStatement(sql);
                for(int i=1;i<=108;i++) {
                    //每次循环都将数据暂存到ps上
                    ps.setString(1, "好汉"+i);
                    ps.setString(2, "打劫");
                    ps.setInt(3, 0);
                    ps.setDate(4, 
                        Date.valueOf("2017-01-23"));
                    ps.setDouble(5, 6000.0);
                    ps.setDouble(6, 4000.0);
                    ps.setInt(7, 9);
                    ps.addBatch();
                    //每循环50次发送一次数据
                    if(i%50==0) {
                        ps.executeBatch();
                        //清空ps中的数据,以便于
                        //暂存下一轮的数据
                        ps.clearBatch();
                    }
                }
                //循环结束后,为了避免有零头(8),
                //再单独批量发送一次数据.由于这
                //是最后一次发送,所以不用清空ps了
                ps.executeBatch();
                conn.commit();
            } catch (SQLException e) {
                e.printStackTrace();
                try {
                    conn.rollback();
                } catch (SQLException e1) {
                    e1.printStackTrace();
                }
            } finally {
                DBUtil.close(conn);
            }
        }
        
        /**
         * 添加部门及员工数据
         * 添加员工时需要获取到部门的ID
         */
        @Test
        public void test4() {
            //假设页面传入的数据是
            //部门
            String dname = "财务部";
            String loc = "杭州";
            //员工
            String ename = "郭嘉";
            String job = "谋士";
            int mgr = 0;
            Date hiredate = 
                Date.valueOf("2017-01-23");
            double sal = 6000.0;
            double comm = 2000.0;
            
            Connection conn = null;
            try {
                conn = DBUtil.getConnection();
                conn.setAutoCommit(false);
                //增加部门
                String sql = 
                    "insert into depts values("
                    + "depts_seq.nextval,?,?)";
                //参数2是一个数组,声明需要ps记住
                //的字段的名称,ps在执行SQL时会
                //记住这些字段的值.
                PreparedStatement ps = 
                    conn.prepareStatement(
                        sql, new String[]{"deptno"});
                ps.setString(1, dname);
                ps.setString(2, loc);
                ps.executeUpdate();
                //获取部门ID
                //返回的结果集中存储了一条数据,
                //该行数据包括我们让ps记录的所有字段.
                ResultSet rs = ps.getGeneratedKeys();
                System.out.println("rs"+rs);  
                //rsorg.apache.commons.dbcp.DelegatingResultSet@27efef64
                rs.next();
                //获取ps记录的字段时必须使用序号
                int deptno = rs.getInt(1);
                System.out.println("deptno"+deptno);  //deptno 4
                //增加员工
                String sql2 = 
                    "insert into emps values("
                    + "emps_seq.nextval,"
                    + "?,?,?,?,?,?,?)";
                PreparedStatement ps2 = 
                    conn.prepareStatement(sql2);
                ps2.setString(1, ename);
                ps2.setString(2, job);
                ps2.setInt(3, mgr);
                ps2.setDate(4, hiredate);
                ps2.setDouble(5, sal);
                ps2.setDouble(6, comm);
                ps2.setInt(7, deptno);
                ps2.executeUpdate();
                conn.commit();
            } catch (SQLException e) {
                e.printStackTrace();
                try {
                    conn.rollback();
                } catch (SQLException e1) {
                    e1.printStackTrace();
                }
            } finally {
                DBUtil.close(conn);
            }
        }
        
    }
  • 相关阅读:
    dubbo入门(一)
    java中文件操作《一》
    Unity 游戏框架搭建 2019 (七) 自定义快捷键
    凉鞋:我所理解的框架 【Unity 游戏框架搭建】
    Unity 游戏框架搭建 2019 (六) MenuItem 复用
    Unity 游戏框架搭建 2019 (五) 打开所在文件夹
    Unity 游戏框架搭建 2019 (四) 导出 UnityPackage
    Unity 游戏框架搭建 2019 (三) 生成文件名到剪切板
    Unity 游戏框架搭建 2019 (二) 文本复制到剪切板
    Unity 游戏框架搭建 2019 (一) 简介与第一个示例文件名的生成
  • 原文地址:https://www.cnblogs.com/tangshengwei/p/6348037.html
Copyright © 2011-2022 走看看