JDBC

1. JDBC的概念

Java Database Connectivity,是Java语言中用来规范客户端程序如何来访问数据库的应用程序接口,提供了诸如查询和更新数据库中数据的方法。
在这里插入图片描述

1.1 快速入门

步骤:

  1. 导入驱动jar包
    把要导入的包复制文件夹到 out 目录下的 meta-inf,在下面新建 lib 把 jar 放进去,右键 -> Add As Library即可
  2. 注册驱动
  3. 获取数据库连接对象 Connection
  4. 定义sql
  5. 获取执行sql语句的对象 Startement
  6. 执行sql,接受返回结果
  7. 处理结果
  8. 释放资源
public class Demo1 {
    public static void main(String[] args) throws Exception {
        // 1
        // 2
        Class.forName("com.mysql.cj.jdbc.Driver");
        // 3
        Connection con = DriverManager.getConnection("jdbc:mysql://localhost:3306/db1?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai", "root", "123456Ljq");
        // 4
        String sql = "update account set balance = 500 where id = 1";
        // 5
        Statement statement = con.createStatement();
        // 6
        int count = statement.executeUpdate(sql);
        // 7
        System.out.println(count);
        // 8
        statement.close();
        con.close();
    }
}
1.2 JDBC各个类详解
1. DriverManager

驱动管理对象

功能:

  • 注册驱动: 告诉程序应该使用哪一个数据库驱动jar
    mysql5之后的驱动jar包可以省略注册驱动的步骤
  • 获得数据库连接
    • 方法: static Connection getConnection(String url, String user, String password)
    • 参数:
      • url:指定连接的路径 jdbc:mysql://ip地址或域名:端口号/数据库名称(如果连接的是本机mysql服务器,并且mysql服务器默认端口是3306,则可以简写为jdbc:mysql:///数据库名称)
      • user:用户名
      • password:密码
2. Connection

数据库连接对象

功能:

  • 获取执行 sql 对象
    • Statement createStatement()
    • PreparedStatement prepareStatement(String sql)
  • 管理事务
    • 开启事务:void setAutoCommit(boolean autoCommit),调用该方法设置参数为false,即开启事务
    • 提交事务:commit()
    • 回滚事务:rollback()
3. Startement

执行sql语句对象

执行sql:

  1. boolean execute(String sql):可以执行任意的sql;
  2. int executeUpdate(String sql):执行DML(insert、update、delete)语句、DDL(create、alter、drop)语句,返回值是印象的行数;
  3. ResultSet executeQuery(String sql):执行DQL(select)语句。

练习: 添加、删除、修改account表的数据

public class Demo2 {
    public static void main(String[] args) {
        Connection con = null;
        Statement sta = null;
        try{
            // 1. 注册驱动
            Class.forName("com.mysql.cj.jdbc.Driver");
            // 2. 定义sql
            String sql = "insert into account values (null, '张三', 1000)";
            //String sql = "update account set balance = 1500 where id = 3";  //修改
            //String sql = "delete from account where id = 3";   // 删除
            // 3. 获取Connection对象
            con = DriverManager.getConnection("jdbc:mysql://localhost:3306/db1?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai", "root", "123456Ljq");
            // 4. 获取执行sql对象Statement
            sta = con.createStatement();
            // 5. 执行sql语句
            int i = sta.executeUpdate(sql);
            // 6. 处理结果
            System.out.println(i);
            if(i > 0) {
                System.out.println("添加成功!");
            } else {
                System.out.println("添加失败!");
            }
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            // 7. 释放资源
            if(sta != null) {
                try {
                    sta.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if(con != null) {
                try {
                    con.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
4. ResultSet

结果集对象,封装查询结果

  • boolean next():游标向下移动一格,判断当前行是否是最后一行末尾,没数据则返回false
  • getXxx(参数):
    • 获取数据,Xxx代表数据类型(比如getInt、getString)
    • 参数:
      • int:代表列的编号,从1开始,如getString(1)
      • String:代表列名称,如getDouble(“balance”)
public class Demo4 {
    public static void main(String[] args) {
        Connection con = null;
        Statement sta = null;
        ResultSet rs = null;
        try{
            // 1. 注册驱动
            Class.forName("com.mysql.cj.jdbc.Driver");
            // 2. 定义sql
            String sql = "select * from account";
            // 3. 获取Connection对象
            con = DriverManager.getConnection("jdbc:mysql://localhost:3306/db1?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai", "root", "123456Ljq");
            // 4. 获取执行sql对象Statement
            sta = con.createStatement();
            // 5. 执行sql语句
            rs = sta.executeQuery(sql);
            // 6. 处理结果
            /*
            (获取第一行数据)
            rs.next();  // 游标向下移动一行,指向第一行数据,然后获取每个数据并输出
            int id = rs.getInt(1);
            String name = rs.getString("name");
            double balance = rs.getDouble(3);
            System.out.println(id + "-" + name + "-" + balance);
            */
            // 游标向下移动一行,判断是否有数据,若有则获取每个数据并输出
            while(rs.next()) {
                int id = rs.getInt(1);
                String name = rs.getString("name");
                double balance = rs.getDouble(3);
                System.out.println(id + "-" + name + "-" + balance);
            }
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            // 7. 释放资源
            if(sta != null) {
                try {
                    sta.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if(con != null) {
                try {
                    con.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if(rs != null) {
                try {
                    rs.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
5. PreparedStatement

执行sql的对象

sql注入问题: 在拼接sql时,有一些sql的特殊关键字参与字符串的拼接,会造成安全性问题。

解决sql注入问题: 使用PreparedStatement对象来解决

sql的参数使用?作为占位符,例如 select * from user where username = ? and password = ?

给 ?赋值: setXxx(参数1, 参数2),参数1:?的位置编号(从1开始),参数2:?的值

    public boolean login(String username, String password) {
        if(username == null || password == null) {
            return false;
        }
        Connection con = null;
        PreparedStatement preparedStatement = null;
        Statement sta = null;
        ResultSet rs = null;
        try{
            con = JDBCUtils.getConnection();
            String sql = "select * from account where username = ? and password = ?";
            preparedStatement = con.prepareStatement(sql);
            preparedStatement.setString(1, username);
            preparedStatement.setString(2, password);
            rs = preparedStatement.executeQuery();
            return rs.next();
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            JDBCUtils.close(rs, preparedStatement, con);
        }
        return false;
    }
1.3 JDBC工具类

目的:简化书写

// JDBC 工具类
public class JDBCUtils {
    private static String url;
    private static String user;
    private static String password;
    private  static String driver;


    //文件读取,只会执行一次,使用静态代码块
    static {
        //读取文件,获取值
        try {
            //1.创建Properties集合类
            Properties pro = new Properties();
            //获取src路径下的文件--->ClassLoader类加载器
            /*
            ClassLoader classLoader = JDBCUtils.class.getClassLoader();
            URL resource = classLoader.getResource("jdbc.properties");;
            String path = resource.getPath();
            */
            //2.加载文件
            pro.load(new FileReader("D:\\wenjian\\Project01\\src\\JDBC\\jdbc.properties"));
            //3获取数据
            url = pro.getProperty("url");
            user = pro.getProperty("user");
            password = pro.getProperty("password");
            driver = pro.getProperty("driver");
            //4.注册驱动
            Class.forName(driver);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
    /**
     * 获取连接
     * @return 连接对象
     */
    public static Connection getConnection() throws SQLException {
        Connection conn = DriverManager.getConnection(url, user, password);
        return conn;
    }

    /**
     * 释放资源
     * @param rs
     * @param st
     * @param conn
     */
    public static void close(ResultSet rs, Statement st,Connection conn){
        if (rs != null){
            try {
                rs.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if(st != null){
            try {
                st.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if (conn != null){
            try {
                conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }

    public static void close(Statement stmt, Connection con) {
        if(stmt != null) {
            try {
                stmt.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if(con != null) {
            try {
                con.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
}

简化后使用

public class Demo5 {
    public static void main(String[] args) {
        Connection con = null;
        Statement sta = null;
        ResultSet rs = null;
        try{
            con = JDBCUtils.getConnection();
            String sql = "select * from account";
            sta = con.createStatement();
            rs = sta.executeQuery(sql);
            while(rs.next()) {
                int id = rs.getInt(1);
                String name = rs.getString("name");
                double balance = rs.getDouble(3);
                System.out.println(id + "-" + name + "-" + balance);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            JDBCUtils.close(rs, sta, con);
        }
    }
}
1.4 JDBC管理事务

使用Connection对象来管理事务

  • 在执行sql之前开启事务
  • 在 所有sql都执行完提交事务
  • 在catch中回滚事务
public class Demo6 {
    public static void main(String[] args) {
        Connection con = null;
        // 开启事务
        try {
            con.setAutoCommit(false);
        } catch (SQLException e) {
            e.printStackTrace();
        }

        PreparedStatement pre1 = null;
        PreparedStatement pre2 = null;
        try {
            con = JDBCUtils.getConnection();
            String sql1 = "update account set balance = balance - ? where id = ?";
            String sql2 = "update account set balance = balance + ? where id = ?";
            pre1 = con.prepareStatement(sql1);
            pre2 = con.prepareStatement(sql2);
            pre1.setDouble(1, 500);
            pre2.setDouble(1, 500);
            pre1.setInt(2, 1);
            pre2.setInt(2, 2);
            pre1.executeUpdate();
            pre2.executeUpdate();
            // 提交事务
            con.commit();
        } catch (SQLException e) {
            // 事务回滚
            try {
                if(con != null) {
                    con.rollback();
                }
            } catch (SQLException ex) {
                ex.printStackTrace();
            }
            e.printStackTrace();
        } finally {
            JDBCUtils.close(pre1, con);
            JDBCUtils.close(pre2, null);
        }
        System.out.println("111");
    }
}

2. 数据库连接池

概念:其实就是一个容器(集合),用来存放数据库连接

当系统初始化好后,容器被创建,容器中会申请一些连接对象,当用户来访问数据库时,从容器中获取连接对象,用户访问完之后,会将连接对象归还给容器

好处:节约资源、用户访问高效

实现:

  • 标准接口:DataSource,java.sql包下
    • 获取连接:getConnection()
    • 归还链接:如果连接对象Connection是从连接池中获取的,那么调用Connection.close()方法,就不会再关闭连接了,而是归还连接
  • 一般我们不去实现它,有数据库厂商来实现
    • C3P0
    • Druid
2.1 C3P0

使用步骤:

  1. 导入jar包
  2. 定义配置文件
  3. 创建核心对象 数据库连接池对象:ComboPooledDataSource
  4. 获取连接:getConnection
public class Demo1_C3P0 {
    public static void main(String[] args) throws SQLException {
        // 1. 创建数据库连接池对象
        DataSource ds = new ComboPooledDataSource();
        // 2. 获取连接对象
        Connection con = ds.getConnection();
        System.out.println(con);
    }
}
2.2 Druid

步骤:

  1. 导入jar包
  2. 定义配置文件
  3. 获取数据库连接池对象,通过工厂来获取:DruidDataSourceFactory
  4. 获取连接
public class Demo1_Druid {
    public static void main(String[] args) throws Exception {
        // 加载配置文件
        Properties pro = new Properties();
        InputStream is = Demo1_Druid.class.getClassLoader().getResourceAsStream("druid.properties");
        pro.load(is);
        // 获得连接池对象
        DataSource ds = DruidDataSourceFactory.createDataSource(pro);
        // 获得链接
        Connection con = ds.getConnection();
        System.out.println(con);
    }
}

定义工具类

public class JDBCUtils {
    // 定义成员变量
    private static DataSource ds;

    static {
        // 1. 加载配置文件
        Properties pro = new Properties();
        try {
            pro.load(JDBCUtils.class.getClassLoader().getResourceAsStream("druid.properties"));
            // 2. 获取DataSource对象
            ds = DruidDataSourceFactory.createDataSource(pro);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    // 获取连接
    public static Connection getConnection() throws SQLException {
        return ds.getConnection();
    }

    // 释放资源
    public static void close(ResultSet res, Statement stmt, Connection con) {
        if(res != null) {
            try {
                res.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if(stmt != null) {
            try {
                stmt.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }

        if(con != null) {
            try {
                con.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }

    public static void close(Statement stmt, Connection con) {
        close(null, stmt, con);
    }

    // 获取连接池
    public static DataSource getDataSource() {
        return ds;
    }
}

3. JDBCTemplate

JdbcTemplate是Spring对JDBC的封装,目的是使JDBC更加易于使用。JdbcTemplate是Spring的一部分。

在JdbcTemplate中执行SQL语句的方法大致分为3类:

  1. execute:可以执行所有SQL语句,一般用于执行DDL语句。
  2. update:用于执行INSERT、UPDATE、DELETE等DML语句。
  3. queryXxx:用于DQL数据查询语句。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值