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);
            }
        }
        
    }
  • 相关阅读:
    100LS练习方法
    甲方开源项目
    linux端口转发方式
    内网的一些穿透工具
    Checkpoint防火墙(一)
    2020目标
    Linux逻辑卷的扩容和缩小
    linux挂载磁盘
    Selinux介绍
    以太坊私链搭建
  • 原文地址:https://www.cnblogs.com/tangshengwei/p/6348037.html
Copyright © 2011-2022 走看看