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);
            //[email protected]
            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);
        }
    }

}
时间: 2024-10-08 13:22:51

Unit02: JDBC核心API的相关文章

JDBC核心API

JDBC核心API在java.sql.*和javax.sql.* 1.Driver接口:表示Java驱动程序接口,具体的数据库厂商要实现其此接口 connect(url.propertis):连接数据库的方法 url:连接数据库的URL url语法格式:jdbc协议:数据库子协议://主机:端口/数据库 user:数据库用户名 password:数据库用户密码 2.DriverManager类:驱动管理器的类,管理所有的注册驱动程序 registerDriver(driver):注册驱动 Con

JavaEE JDBC 核心API

JDBC接口核心的API @author ixenos java.sql.*   和  javax.sql.* |- Driver接口: 表示java驱动程序接口.所有的具体的数据库厂商要来实现此接口. |- connect(url, properties):  连接数据库的方法. url: 连接数据库的URL URL语法: jdbc协议:数据库子协议://主机:端口/数据库 user: 数据库的用户名 password: 数据库用户密码 |- DriverManager类: 驱动管理器类,用于

配置文件详解和核心api讲解

一.配置文件详解 1.映射文件详解 1.映射配置文件的位置和名称没有限制. -建议:位置:和实体类放在统一目录下.  名称:实体类名称.hbm.xml.    2.在映射配置文件中,标签内的name属性的值要和实体内的属性对应. (1)class标签内的name的值为实体类的全路径. (2)property标签内的name的值为实体类的属性. (3)id标签内的name的值为实体类的属性. (4)id和property标签内的column属性可以不写. (5)id和property标签内有一个t

Java核心API需要掌握的程度

分类: java技术2009-08-29 01:03 213人阅读 评论(0) 收藏 举报 javaapiswingxmlio Java的核心API是非常庞大的,这给开发者来说带来了很大的方便,经常人有评论,java让程序员变傻. 但是一些内容我认为是必须掌握的,否则不可以熟练运用java,也不会使用就很难办了. 1.java.lang包下的80%以上的类的功能的灵活运用. 2.java.util包下的80%以上的类的灵活运用,特别是集合类体系.正规表达式.时间.属性.和Timer. 3.jav

Hibernate入门----核心API

hibernate 核心APIConfigurationConfiguration : 封装Hibernate系统配置信息的对象使用hibernate.cfg.xml加载配置: /** * Configuration().configure(); ,默认读取classpath下hibernate.cfg.xml文件 * Configuration().configure("配置文件名"); 不常用 /config/ hibernate.cfg.xml 加载 */ Configurati

Hibernate的核心API ---- 入门学习

叙:学习hibernate是必不可少的要了解其核心的API,下面电虫就核心API进行记录学习: Hibernate核心API Hibernate核心API有configuration.SessonFactory.Session.Transaction等,在Session中有增删改查等小地API,下面进行详细学习: 学习要有目标有方向,所以从一段代码中从上到下的进行研读不失为一种高效率的学习方法,学习模板代码如下所示: 1 package com.java.hibernate.demo1; 2 3

三大框架 之 Hibernate框架概述(概述、配置、核心API)

目录 Hibernate框架概述 什么是框架 hibernate简介(JavaEE技术三层架构所用到的技术) hibernate是什么框架 ORM hibernate好处 Hibernate基本使用 下载框架 Hibernate目录 使用 常见配置 映射配置 核心配置 核心API Configuration SessionFactory sessionFactory简介 配置连接池 查看日志 工具类 session session的api Hibernate框架概述 什么是框架 软件的一个半成品

Activiti6系列(5)- 核心API

前言 本来想把<疯狂工作流讲义-activiti6.0>这本书里面的实例拿过来,但是这本书我看完后,认为里面编写的activiti6的核心API代码片段不是很清晰,有不少需要雕琢的地方才好形成一篇博客. 所以我就把以前看过的黑马activiti5的案例拿过来放到activiti6.0依赖中运行测试,可以正常使用,说明5和6的核心API也就是最常用的那些其实没多少区别,而黑马的activiti核心API的代码片段写的更加通俗易懂,注释简洁,一目了然,就摘取了过来. 一.代码创建表 package

笔记-Node.js中的核心API之HTTP

最近正在学习Node,在图书馆借了基本关于Node的书,同时在网上查阅资料,颇有收获,但是整体感觉对Node的理解还是停留在一个很模棱两可的状态.比如Node中的模块,平时练习就接触到那么几个,其他的一些模块暂时只会在学习的时候接触到,不常用便就荒废了.正所谓好记心不如烂笔头,多做笔记还是更有利于理解和记忆.自己做的总结也方便回头复习,所以决定踏上漫长的修炼之旅-- Node提供了许多API,其中一些比较重要.这些核心的API是所有Node应用的支柱,你会不停的用到他们. HTTP服务器 Nod