【 JavaWeb 】- 1 JDBC

    科技2025-03-31  24

    1 JDBC 简介

    1.1 客户端操作 MySQL 数据库的三种方式:

    使用第三方客户端来访问 MySQL:SQLyog、Navicat、SQLWave、MyDB Studio、EMS SQL Manager for MySQL 使用 MySQL 自带的命令行方式通过 Java 来访问 MySQL 数据库,今天要学习的内容

    1.2 JDBC基本概念

    概念: Java DataBase Connectivity Java 数据库连接, Java语言操作数据库

    JDBC 规范定义接口,具体的实现由各大数据库厂商来实现。

    JDBC本质: 其实是官方(sun公司)定义的一套操作所有关系型数据库的规则,即接口。 各个数据库厂商去实现这套接口,提供数据库驱动jar包。我们可以使用这套接口(JDBC)编程,真正执行的代码是驱动jar包中的实现类。

    JDBC 是 Java 访问数据库的标准规范,真正怎么操作数据库还需要具体的实现类,也就是数据库驱动。每个数据库厂商根据自家数据库的通信格式编写好自己数据库的驱动。所以我们只需要会调用 JDBC 接口中的方法即可,数据库驱动由数据库厂商提供。

    使用 JDBC 的好处:

    程序员如果要开发访问数据库的程序,只需要会调用 JDBC 接口中的方法即可,不用关注类是如何实现的。使用同一套 Java 代码,进行少量的修改就可以访问其他 JDBC 支持的数据库


    2 JDBC 入门程序

    2.1 快速入门

    下载mysql 连接数据库的驱动,下载地址:https://www.mysql.com/products/connector/

    解压:

    下面是一些字节码文件:

    使用 JDBC 开发使用到的包:

    会使用到的包说明java.sql所有与 JDBC 访问数据库相关的接口和类javax.sql数据库扩展包,提供数据库额外的功能。如:连接池数据库的驱动由各大数据库厂商提供,需要额外去下载,是对 JDBC 接口实现的类

    JDBC 的核心 API

    接口或类作用DriverManager 类1) 管理和注册数据库驱动;2) 得到数据库连接对象Connection 接口一个连接对象,可用于创建 Statement 和 PreparedStatement 对象Statement 接口一个 SQL 语句对象,用于将 SQL 语句发送给数据库服务器。PreparedStatemen 接口一个 SQL 语句对象,是 Statement 的子接口ResultSet 接口用于封装数据库查询的结果集,返回给客户端 Java 程序

    准备数据:

    CREATE TABLE account ( id INT PRIMARY KEY AUTO_INCREMENT, NAME VARCHAR(10), balance DOUBLE ); -- 添加数据 INSERT INTO account (NAME, balance) VALUES ('Jack', 1000), ('Rose', 1000);

    步骤:

    1、导入驱动jar包

    复制 mysql-connector-java-5.1.47-bin.jar 到项目的 libs 目录下右键–>Add As Library 2、加载和注册驱动 3、获取数据库连接对象 Connection 4、定义sql 5、获取执行sql语句的对象 Statement 6、执行sql,接受返回结果 7、处理结果 8、释放资源

    代码实现:

    package cn.ys.jdbc; import java.sql.Connection; import java.sql.DriverManager; import java.sql.Statement; /** * JDBC入门 */ public class JDBCDemo1 { public static void main(String[] args) throws Exception { // 1. 导入驱动jar包 // 2.注册驱动 Class.forName("com.mysql.jdbc.Driver"); // 3.获取数据库连接对象 Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/javaee", "yangshuo", "123456"); // 4.定义sql语句 String sql = "update account set balance = 500 where id = 1"; // 5.获取执行sql的对象 Statement Statement stmt = conn.createStatement(); // 6.执行sql int count = stmt.executeUpdate(sql); // 7.处理结果 System.out.println(count); // 8.释放资源 stmt.close(); conn.close(); } }


    3 JDBC 接口 和 类 详解

    3.1 DriverManager:驱动管理对象

    注意: 使用时,导的包为 import java.sql.DriverManager;,是接口;而实际用的是 libs 文件夹下面的实现类。

    ① 注册驱动:告诉程序该使用哪一个数据库驱动jar。

    疑问:为什么这样可以注册驱动?

    public class Demo1 { public static void main(String[] args) throws ClassNotFoundException { //抛出类找不到的异常,注册数据库驱动 Class.forName("com.mysql.jdbc.Driver"); } }

    com.mysql.jdbc.Driver 源代码:

    // Driver 接口,所有数据库厂商必须实现的接口,表示这是一个驱动类。 public class Driver implements java.sql.Driver { public Driver() throws SQLException { } static { try { DriverManager.registerDriver(new Driver()); //注册数据库驱动 } catch (SQLException var1) { throw new RuntimeException("Can't register driver!"); } } }

    注意: mysql5之后的驱动jar包可以省略注册驱动的步骤。Class.forName这句话可以省略。

    原因:该jar包下面有了下面的配置文件,不写,会自动读取配置注册

    ② 获取数据库连接:

    类中的方法:

    DriverManager 类中的静态方法描述Connection getConnection (String url, String user, String password)通过连接字符串,用户名,密码来得到数据库的连接对象Connection getConnection (String url, Properties info)通过连接字符串,属性对象来得到连接对象

    使用 JDBC 连接数据库的四个参数:

    JDBC 连接数据库的四个参数说明用户名登录的用户名密码登录的密码连接字符串 URL不同的数据库 URL 是不同的,mysql 的写法:jdbc:mysql://localhost:3306/数据库[?参数名=参数值]驱动类的字符串名com.mysql.jdbc.Driver

    连接数据库的 URL 地址格式: 协议名:子协议://服务器名或 IP 地址:端口号/数据库名?参数=参数值

    MySQL 写法: 乱码的处理: 如果数据库出现乱码,可以指定参数: ?characterEncoding=utf8,表示让数据库以 UTF-8 编码来处理数据。 jdbc:mysql://localhost:3306/数据库?characterEncoding=utf8

    例子:

    package cn.ys.jdbc; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; /** * 得到连接对象 */ public class Demo2 { public static void main(String[] args) throws SQLException { String url = "jdbc:mysql://localhost:3306/day24"; //1) 使用用户名、密码、URL 得到连接对象 Connection connection = DriverManager.getConnection(url, "root", "root"); //com.mysql.jdbc.JDBC4Connection@68de145 System.out.println(connection); } }

    3.2 Connection 接口:数据库连接对象

    Connection 作用: Connection 接口,具体的实现类由数据库的厂商实现,代表一个连接对象。

    Connection 方法:

    Connection 接口中的方法描述Statement createStatement()创建一条 SQL 语句对象

    功能:

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

    3.3 Statement 接口:执行 sql 的对象

    JDBC 访问数据库的步骤:

    注册和加载驱动(可以省略)获取连接Connection 获取 Statement 对象使用 Statement 对象执行 SQL 语句返回结果集释放资源

    Statement 作用: 代表一条语句对象,用于发送 SQL 语句给服务器,用于执行静态 SQL 语句并返回它所生成结果的对象。

    Statement 接口中的方法:

    boolean execute(String sql) :可以执行任意的sql(了解 )int executeUpdate(String sql) 执行DML(insert、update、delete)语句、DDL(create,alter、drop)语句返回值:影响的行数,可以通过这个影响的行数判断DML语句是否执行成功,返回值>0的则执行成功,反之,则失败。 ResultSet executeQuery(String sql) 执行DQL(select)语句,执行查询的操作。参数:SQL 语句。返回值:查询的结果集。

    释放资源:

    需要释放的对象:ResultSet 结果集,Statement 语句,Connection 连接释放原则:先开的后关,后开的先关。ResultSet  Statement  Connection放在哪个代码块中:finally 块

    例子:

    account表 添加一条记录account表 修改记录account表 删除一条记录DDL(create,alter、drop)语句 package cn.ys.jdbc; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import java.sql.Statement; /** * account表 添加一条记录 insert 语句 */ public class JDBCDemo2 { public static void main(String[] args) { Statement stmt = null; Connection conn = null; try { //1. 注册驱动 Class.forName("com.mysql.jdbc.Driver"); //2. 定义sql String sql = "insert into account values(null,'王五',3000)"; //3.获取Connection对象 conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/javaee", "yangshuo", "123456"); //4.获取执行sql的对象 Statement stmt = conn.createStatement(); //5.执行sql int count = stmt.executeUpdate(sql);//影响的行数 //6.处理结果 System.out.println(count); if(count > 0){ System.out.println("添加成功!"); }else{ System.out.println("添加失败!"); } } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (SQLException e) { e.printStackTrace(); }finally { //stmt.close(); //7. 释放资源 //避免空指针异常 if(stmt != null){ try { stmt.close(); } catch (SQLException e) { e.printStackTrace(); } } if(conn != null){ try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } } } package cn.ys.jdbc; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import java.sql.Statement; /** * account表 修改记录 */ public class JDBCDemo3 { public static void main(String[] args) { Connection conn = null; Statement stmt = null; try { //1. 注册驱动 Class.forName("com.mysql.jdbc.Driver"); //2.获取连接对象 conn = DriverManager.getConnection("jdbc:mysql:///javaee", "yangshuo", "123456"); //3.定义sql String sql = "update account set balance = 1500 where id = 3"; //4.获取执行sql对象 stmt = conn.createStatement(); //5.执行sql int count = stmt.executeUpdate(sql); //6.处理结果 System.out.println(count); if(count > 0){ System.out.println("修改成功!"); }else{ System.out.println("修改失败"); } } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (SQLException e) { e.printStackTrace(); } finally { //7.释放资源 if(stmt != null){ try { stmt.close(); } catch (SQLException e) { e.printStackTrace(); } } if(conn != null){ try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } } } package cn.ys.jdbc; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import java.sql.Statement; /** * account表 删除一条记录 */ public class JDBCDemo4 { public static void main(String[] args) { Connection conn = null; Statement stmt = null; try { //1. 注册驱动 Class.forName("com.mysql.jdbc.Driver"); //2.获取连接对象 conn = DriverManager.getConnection("jdbc:mysql:///javaee", "yangshuo", "123456"); //3.定义sql String sql = "delete from account where id = 3"; //4.获取执行sql对象 stmt = conn.createStatement(); //5.执行sql int count = stmt.executeUpdate(sql); //6.处理结果 System.out.println(count); if(count > 0){ System.out.println("删除成功!"); }else{ System.out.println("删除失败"); } } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (SQLException e) { e.printStackTrace(); } finally { //7.释放资源 if(stmt != null){ try { stmt.close(); } catch (SQLException e) { e.printStackTrace(); } } if(conn != null){ try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } } } package cn.ys.jdbc; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import java.sql.Statement; /** * 执行DDL语句 */ public class JDBCDemo5 { public static void main(String[] args) { Connection conn = null; Statement stmt = null; try { //1. 注册驱动 Class.forName("com.mysql.jdbc.Driver"); //2.获取连接对象 conn = DriverManager.getConnection("jdbc:mysql:///javaee", "yangshuo", "123456"); //3.定义sql String sql = "create table student (id int , name varchar(20))"; //4.获取执行sql对象 stmt = conn.createStatement(); //5.执行sql int count = stmt.executeUpdate(sql); //6.处理结果 System.out.println(count); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (SQLException e) { e.printStackTrace(); } finally { //7.释放资源 if(stmt != null){ try { stmt.close(); } catch (SQLException e) { e.printStackTrace(); } } if(conn != null){ try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } } }

    3.4 ResultSet 接口:结果集对象,封装查询结果

    作用: 封装数据库查询的结果集,对结果集进行遍历,取出每一条记录。 接口中的方法:

    ResultSet 接口中的方法描述boolean next()游标向下移动一行,判断当前行是否是最后一行末尾(是否有数据),如果是,则返回false,如果不是则返回true数据类型 getXxx()1) 通过字段名,参数是 String 类型。返回不同的类型;2) 通过列号,参数是整数,从 1 开始。返回不同的类型

    补充: getXxx(参数):获取数据

    Xxx:代表数据类型 如: int getInt() , String getString()参数: 1. int:代表列的编号,从1开始 如: getString(1) 2. String:代表列名称。 如: getDouble(“balance”)

    注意: 使用步骤:

    游标向下移动一行判断是否有数据获取数据

    常用数据类型转换表: 注:java.sql.Date、Time、Timestamp(时间戳),三个共同父类是:java.util.Date

    package cn.ys.jdbc; import java.sql.*; /** * 执行DQL语句 */ public class JDBCDemo6 { public static void main(String[] args) { Connection conn = null; Statement stmt = null; ResultSet rs = null; try { //1. 注册驱动 Class.forName("com.mysql.jdbc.Driver"); //2.获取连接对象 conn = DriverManager.getConnection("jdbc:mysql:///javaee", "yangshuo", "123456"); //3.定义sql String sql = "select * from account"; //4.获取执行sql对象 stmt = conn.createStatement(); //5.执行sql rs = stmt.executeQuery(sql); //6.处理结果 //循环判断游标是否是最后一行末尾。 while(rs.next()){ //获取数据 //6.2 获取数据 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(rs != null){ try { rs.close(); } catch (SQLException e) { e.printStackTrace(); } } if(stmt != null){ try { stmt.close(); } catch (SQLException e) { e.printStackTrace(); } } if(conn != null){ try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } } }

    关于 ResultSet 接口中的注意事项:

    如果光标在第一行之前,使用 rs.getXX()获取列值,报错:Before start of result set如果光标在最后一行之后,使用 rs.getXX()获取列值,报错:After end of result set使用完毕以后要关闭结果集 ResultSet,再关闭 Statement,再关闭 Connection

    3.5 PreparedStatement 接口:执行 sql 的对象

    SQL注入问题:

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

    输入用户随便,输入密码:a’ or ‘a’ = 'asql:select * from user where username = ‘fhdsjkf’ and password = ‘a’ or ‘a’ = ‘a’

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

    继承结构与作用:

    PreparedStatement 是 Statement 接口的子接口,继承于父接口中所有的方法。它是一个预编译的 SQL 语句。

    PreparedSatement 的执行原理:

    因为有预先编译的功能,提高 SQL 的执行效率。可以有效的防止 SQL 注入的问题,安全性更高。

    PreparedStatement 接口中的方法:

    PreparedSatement 的好处:

    prepareStatement()会先将 SQL 语句发送给数据库预编译。PreparedStatement 会引用着预编译后的结果。 可以多次传入不同的参数给 PreparedStatement 对象并执行。减少 SQL 编译次数,提高效率。安全性更高,没有 SQL 注入的隐患。提高了程序的可读性

    预编译的SQL:参数使用 ? 作为占位符

    使用 PreparedStatement 的步骤:

    导入驱动jar包 mysql-connector-java-5.1.37-bin.jar注册驱动获取数据库连接对象 Connection定义sql 注意:sql的参数使用?作为占位符。 如:select * from user where username = ? and password = ?; 获取执行sql语句的对象 PreparedStatement Connection.prepareStatement(String sql)给?赋值: 方法: setXxx(参数1,参数2) 参数1:?的位置编号 从1 开始参数2:?的值 执行sql,接受返回结果,不需要传递sql语句处理结果释放资源

    注意:后期都会使用PreparedStatement来完成增删改查的所有操作

    可以防止SQL注入效率更高

    4 JDBC 工具类 - JDBCUtils

    4.1 什么时候自己创建工具类?

    如果一个功能经常要用到,我们建议把这个功能做成一个工具类,可以在不同的地方重用。

    4.2 需求:

    上面写的代码中出现了很多重复的代码,可以把这些公共代码抽取出来。

    4.3 抽取JDBC工具类 : JDBCUtils

    创建类 JdbcUtil 包含 3 个方法:

    注册驱动也抽取抽取一个方法获取连接对象 需求:不想传递参数(麻烦),还得保证工具类的通用性。解决:配置文件,jdbc.properties 抽取一个方法释放资源: close(Connection conn, Statement stmt),close(Connection conn, Statement stmt, ResultSet rs)

    代码实现:

    jdbc.properties:

    url=jdbc:mysql://localhost:3306/javaee user=yangshuo password=123456 driver=com.mysql.jdbc.Driver package cn.ys.utils; import java.io.FileReader; import java.io.IOException; import java.net.URL; import java.sql.*; import java.util.Properties; /** * 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 res = classLoader.getResource("jdbc.properties"); String path = res.getPath(); //2. 加载文件 pro.load(new FileReader(path)); //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 { return DriverManager.getConnection(url, user, password); } /** * 释放资源 * @param stmt * @param conn */ public static void close(Statement stmt,Connection conn){ if( stmt != null){ try { stmt.close(); } catch (SQLException e) { e.printStackTrace(); } } if( conn != null){ try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } /** * 释放资源 * @param stmt * @param conn */ public static void close(ResultSet rs,Statement stmt, Connection conn){ if( rs != null){ try { rs.close(); } catch (SQLException e) { e.printStackTrace(); } } if( stmt != null){ try { stmt.close(); } catch (SQLException e) { e.printStackTrace(); } } if( conn != null){ try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } } package cn.ys.jdbc; import cn.ys.entity.Emp; import cn.ys.utils.JDBCUtils; import java.sql.*; import java.util.ArrayList; import java.util.List; /** * * 定义一个方法,查询emp表的数据将其封装为对象,然后装载集合,返回。 */ public class JDBCDemo8 { public static void main(String[] args) { List<Emp> list = new JDBCDemo8().findAll(); System.out.println(list); System.out.println(list.size()); } /** * 使用JDBC工具类,查询所有emp对象 * @return */ public List<Emp> findAll(){ Connection conn = null; Statement stmt = null; ResultSet rs = null; List<Emp> list = null; try { //2.获取连接 conn = JDBCUtils.getConnection(); //3.定义sql String sql = "select * from emp"; //4.获取执行sql的对象 stmt = conn.createStatement(); //5.执行sql rs = stmt.executeQuery(sql); //6.遍历结果集,封装对象,装载集合 Emp emp = null; list = new ArrayList<Emp>(); while(rs.next()){ //获取数据 int id = rs.getInt("id"); String ename = rs.getString("ename"); int job_id = rs.getInt("job_id"); int mgr = rs.getInt("mgr"); Date joindate = rs.getDate("joindate"); double salary = rs.getDouble("salary"); double bonus = rs.getDouble("bonus"); int dept_id = rs.getInt("dept_id"); // 创建emp对象,并赋值 emp = new Emp(); emp.setId(id); emp.setEname(ename); emp.setJob_id(job_id); emp.setMgr(mgr); emp.setJoindate(joindate); emp.setSalary(salary); emp.setBonus(bonus); emp.setDept_id(dept_id); //装载集合 list.add(emp); } } catch (Exception e) { e.printStackTrace(); } finally { JDBCUtils.close(rs,stmt,conn); } return list; } }

    注意: 上面的 JDBCUtils 工具类,重载了释放资源的方法。 因为:查询比增加和修改 要多释放 一个结果集


    5 JDBC 控制事务

    5.1 JDBC 事务的处理

    之前我们是使用 MySQL 的命令来操作事务。接下来我们使用 JDBC 来操作银行转账的事务。

    5.2 事务:

    一个包含多个步骤的业务操作。如果这个业务操作被事务管理,则这多个步骤要么同时成功,要么同时失败。

    5.3 API 介绍:

    操作:

    开启事务提交事务回滚事务

    5.4 使用 Connection 对象来管理事务

    开启事务:setAutoCommit(boolean autoCommit) :调用该方法设置参数为false,即开启事务 在执行sql之前开启事务 提交事务:commit() 当所有sql都执行完提交事务 回滚事务:rollback() 在catch中回滚事务

    5.5 开发步骤:

    获取连接开启事务获取到 PreparedStatement使用 PreparedStatement 执行两次更新操作正常情况下提交事务出现异常回滚事务最后关闭资源 package cn.ys.jdbc; import cn.ys.utils.JDBCUtils; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.SQLException; /** * 事务操作 */ public class JDBCDemo10 { public static void main(String[] args) { Connection conn = null; PreparedStatement pstmt1 = null; PreparedStatement pstmt2 = null; try { //1.获取连接 conn = JDBCUtils.getConnection(); //开启事务 conn.setAutoCommit(false); //2.定义sql //2.1 张三 - 500 String sql1 = "update account set balance = balance - ? where id = ?"; //2.2 李四 + 500 String sql2 = "update account set balance = balance + ? where id = ?"; //3.获取执行sql对象 pstmt1 = conn.prepareStatement(sql1); pstmt2 = conn.prepareStatement(sql2); //4. 设置参数 pstmt1.setDouble(1,500); pstmt1.setInt(2,1); pstmt2.setDouble(1,500); pstmt2.setInt(2,2); //5.执行sql pstmt1.executeUpdate(); // 手动制造异常 int i = 3/0; pstmt2.executeUpdate(); //提交事务 conn.commit(); } catch (Exception e) { //事务回滚 try { if(conn != null) { conn.rollback(); } } catch (SQLException e1) { e1.printStackTrace(); } e.printStackTrace(); }finally { JDBCUtils.close(pstmt1,conn); JDBCUtils.close(pstmt2,null); } } }

    6 JDBC 练习 - 表的数据将其封装为对象

    定义一个方法,查询emp表的数据将其封装为对象,然后装载集合,返回。

    定义Emp类定义方法 public List findAll(){}实现方法 select * from emp;

    6.1 建表语句

    DROP TABLE IF EXISTS emp; CREATE TABLE `emp` ( `id` int(32) NOT NULL AUTO_INCREMENT, `ename` varchar(255) DEFAULT NULL, `job_id` int(32) DEFAULT NULL, `mgr` int(32) DEFAULT NULL, `joindate` date DEFAULT NULL, `salary` double(10,2) DEFAULT NULL, `bonus` double(10,2) DEFAULT NULL, `dept_id` int(32) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; INSERT INTO emp VALUES(1001,'孙悟空1',4,1004,'2010-12-17',8080.0,NULL,20); INSERT INTO emp VALUES(1002,'孙悟空2',3,1002,'2010-12-12',8010.0,NULL,30); INSERT INTO emp VALUES(1003,'孙悟空3',4,1005,'2010-12-13',8120.0,NULL,21); INSERT INTO emp VALUES(1004,'孙悟空4',2,1004,'2010-12-14',8032.0,NULL,23); INSERT INTO emp VALUES(1005,'孙悟空5',3,1003,'2010-12-17',8230.0,NULL,25); INSERT INTO emp VALUES(1006,'孙悟空6',4,1006,'2010-12-19',8110.0,NULL,22); INSERT INTO emp VALUES(1007,'孙悟空7',2,1009,'2010-12-11',8083.0,NULL,43); INSERT INTO emp VALUES(1008,'孙悟空8',4,1000,'2010-12-12',8280.0,NULL,53);

    6.2 定义 EMP 类,封装 Emp 表数据的 JavaBean

    package cn.ys.entity; import java.util.Date; /** * 封装Emp表数据的JavaBean */ public class Emp { private int id; private String ename; private int job_id; private int mgr; private Date joindate; private double salary; private double bonus; private int dept_id; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getEname() { return ename; } public void setEname(String ename) { this.ename = ename; } public int getJob_id() { return job_id; } public void setJob_id(int job_id) { this.job_id = job_id; } public int getMgr() { return mgr; } public void setMgr(int mgr) { this.mgr = mgr; } public Date getJoindate() { return joindate; } public void setJoindate(Date joindate) { this.joindate = joindate; } public double getSalary() { return salary; } public void setSalary(double salary) { this.salary = salary; } public int getDept_id() { return dept_id; } public void setDept_id(int dept_id) { this.dept_id = dept_id; } public double getBonus() { return bonus; } public void setBonus(double bonus) { this.bonus = bonus; } @Override public String toString() { return "Emp{" + "id=" + id + ", ename='" + ename + '\'' + ", job_id=" + job_id + ", mgr=" + mgr + ", joindate=" + joindate + ", salary=" + salary + ", bonus=" + bonus + ", dept_id=" + dept_id + '}'; } }

    6.3 定义一个方法,查询emp表的数据将其封装为对象

    package cn.ys.jdbc; import cn.ys.entity.Emp; import java.sql.*; import java.util.ArrayList; import java.util.List; /** * * 定义一个方法,查询emp表的数据将其封装为对象,然后装载集合,返回。 */ public class JDBCDemo7 { public static void main(String[] args) { List<Emp> list = new JDBCDemo7().findAll(); System.out.println(list); System.out.println(list.size()); } /** * 查询所有emp对象 * @return */ public List<Emp> findAll(){ Connection conn = null; Statement stmt = null; ResultSet rs = null; List<Emp> list = null; try { //1.注册驱动 Class.forName("com.mysql.jdbc.Driver"); //2.获取连接 conn = DriverManager.getConnection("jdbc:mysql:///javaee", "yangshuo", "123456"); //3.定义sql String sql = "select * from emp"; //4.获取执行sql的对象 stmt = conn.createStatement(); //5.执行sql rs = stmt.executeQuery(sql); //6.遍历结果集,封装对象,装载集合 Emp emp = null; list = new ArrayList<Emp>(); while(rs.next()){ //获取数据 int id = rs.getInt("id"); String ename = rs.getString("ename"); int job_id = rs.getInt("job_id"); int mgr = rs.getInt("mgr"); Date joindate = rs.getDate("joindate"); double salary = rs.getDouble("salary"); double bonus = rs.getDouble("bonus"); int dept_id = rs.getInt("dept_id"); // 创建emp对象,并赋值 emp = new Emp(); emp.setId(id); emp.setEname(ename); emp.setJob_id(job_id); emp.setMgr(mgr); emp.setJoindate(joindate); emp.setSalary(salary); emp.setBonus(bonus); emp.setDept_id(dept_id); //装载集合 list.add(emp); } } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (SQLException e) { e.printStackTrace(); }finally { if(rs != null){ try { rs.close(); } catch (SQLException e) { e.printStackTrace(); } } if(stmt != null){ try { stmt.close(); } catch (SQLException e) { e.printStackTrace(); } } if(conn != null){ try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } return list; } }

    7 Spring JDBC

    Spring框架对JDBC的简单封装。提供了一个JDBCTemplate对象简化JDBC的开发

    步骤:

    准备:

    driverClassName=com.mysql.jdbc.Driver url=jdbc:mysql://localhost:3306/javaee username=yangshuo password=123456 # 初始化连接数量 initialSize=5 # 最大连接数 maxActive=10 # 最大等待时间 maxWait=3000 package cn.ys.utils; import com.alibaba.druid.pool.DruidDataSourceFactory; import javax.sql.DataSource; import java.io.IOException; import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.Properties; /** * Druid连接池的工具类 */ public class JDBCUtils { //1.定义成员变量 DataSource private static DataSource ds ; static{ try { //1.加载配置文件 Properties pro = new Properties(); 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(Statement stmt,Connection conn){ /* if(stmt != null){ try { stmt.close(); } catch (SQLException e) { e.printStackTrace(); } } if(conn != null){ try { conn.close();//归还连接 } catch (SQLException e) { e.printStackTrace(); } }*/ close(null,stmt,conn); } public static void close(ResultSet rs , Statement stmt, Connection conn){ if(rs != null){ try { rs.close(); } catch (SQLException e) { e.printStackTrace(); } } if(stmt != null){ try { stmt.close(); } catch (SQLException e) { e.printStackTrace(); } } if(conn != null){ try { conn.close();//归还连接 } catch (SQLException e) { e.printStackTrace(); } } } /** * 获取连接池方法 */ public static DataSource getDataSource(){ return ds; } }

    步骤一:导入jar包

    步骤二:创建 JdbcTemplate 对象。依赖于数据源DataSource

    JdbcTemplate template = new JdbcTemplate(ds);

    步骤三:调用JdbcTemplate的方法来完成CRUD的操作

    update():执行DML语句。增、删、改语句queryForMap():查询结果将结果集封装为map集合,将列名作为key,将值作为value 将这条记录封装为一个map集合 注意:这个方法查询的结果集长度只能是1 queryForList():查询结果将结果集封装为list集合 注意:将每一条记录封装为一个Map集合,再将Map集合装载到List集合中 query():查询结果,将结果封装为JavaBean对象 query的参数:RowMapper一般我们使用BeanPropertyRowMapper实现类。可以完成数据到JavaBean的自动封装new BeanPropertyRowMapper<类型>(类型.class) queryForObject:查询结果,将结果封装为对象 一般用于聚合函数的查询 package cn.ys.jdbcTemplate; import cn.ys.utils.JDBCUtils; import org.springframework.jdbc.core.JdbcTemplate; /** * JdbcTemplate入门 */ public class JdbcTemplateDemo { public static void main(String[] args) { //1.导入jar包 //2.创建JDBCTemplate对象 JdbcTemplate template = new JdbcTemplate(JDBCUtils.getDataSource()); //3.调用方法 String sql = "update account set balance = 5000 where id = ?"; int count = template.update(sql, 1); System.out.println(count); } }

    练习:

    需求:

    修改1号数据的 salary 为 10000添加一条记录删除刚才添加的记录查询id为1的记录,将其封装为Map集合查询所有记录,将其封装为List查询所有记录,将其封装为Emp对象的List集合查询总记录数

    代码

    package cn.ys.entity; import java.util.Date; /** * 封装Emp表数据的JavaBean */ public class Emp { private Integer id; private String ename; private Integer job_id; private Integer mgr; private Date joindate; private Double salary; private Double bonus; private Integer dept_id; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getEname() { return ename; } public void setEname(String ename) { this.ename = ename; } public Integer getJob_id() { return job_id; } public void setJob_id(Integer job_id) { this.job_id = job_id; } public Integer getMgr() { return mgr; } public void setMgr(Integer mgr) { this.mgr = mgr; } public Date getJoindate() { return joindate; } public void setJoindate(Date joindate) { this.joindate = joindate; } public Double getSalary() { return salary; } public void setSalary(Double salary) { this.salary = salary; } public Double getBonus() { return bonus; } public void setBonus(Double bonus) { this.bonus = bonus; } public Integer getDept_id() { return dept_id; } public void setDept_id(Integer dept_id) { this.dept_id = dept_id; } @Override public String toString() { return "Emp{" + "id=" + id + ", ename='" + ename + '\'' + ", job_id=" + job_id + ", mgr=" + mgr + ", joindate=" + joindate + ", salary=" + salary + ", bonus=" + bonus + ", dept_id=" + dept_id + '}'; } } package cn.ys.jdbcTemplate; import cn.ys.entity.Emp; import cn.ys.utils.JDBCUtils; import org.junit.Test; import org.springframework.jdbc.core.BeanPropertyRowMapper; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.RowMapper; import java.sql.Date; import java.sql.ResultSet; import java.sql.SQLException; import java.util.List; import java.util.Map; public class JdbcTemplateDemo { //1. 获取JDBCTemplate对象 private JdbcTemplate template = new JdbcTemplate(JDBCUtils.getDataSource()); /** * 1. 修改1号数据的 salary 为 10000 */ @Test public void test1(){ //2. 定义sql String sql = "update emp set salary = 10000 where id = 1001"; //3. 执行sql int count = template.update(sql); System.out.println(count); } /** * 2. 添加一条记录 */ @Test public void test2(){ String sql = "insert into emp(id,ename,dept_id) values(?,?,?)"; int count = template.update(sql, 1015, "郭靖", 10); System.out.println(count); } /** * 3.删除刚才添加的记录 */ @Test public void test3(){ String sql = "delete from emp where id = ?"; int count = template.update(sql, 1015); System.out.println(count); } /** * 4.查询id为1001的记录,将其封装为Map集合 * 注意:这个方法查询的结果集长度只能是1 */ @Test public void test4(){ String sql = "select * from emp where id = ? or id = ?"; Map<String, Object> map = template.queryForMap(sql, 1001,1002); System.out.println(map); //{id=1001, ename=孙悟空, job_id=4, mgr=1004, joindate=2000-12-17, salary=10000.00, bonus=null, dept_id=20} } /** * 5. 查询所有记录,将其封装为List */ @Test public void test5(){ String sql = "select * from emp"; List<Map<String, Object>> list = template.queryForList(sql); for (Map<String, Object> stringObjectMap : list) { System.out.println(stringObjectMap); } } /** * 6. 查询所有记录,将其封装为Emp对象的List集合 */ @Test public void test6(){ String sql = "select * from emp"; List<Emp> list = template.query(sql, new RowMapper<Emp>() { @Override public Emp mapRow(ResultSet rs, int i) throws SQLException { Emp emp = new Emp(); int id = rs.getInt("id"); String ename = rs.getString("ename"); int job_id = rs.getInt("job_id"); int mgr = rs.getInt("mgr"); Date joindate = rs.getDate("joindate"); double salary = rs.getDouble("salary"); double bonus = rs.getDouble("bonus"); int dept_id = rs.getInt("dept_id"); emp.setId(id); emp.setEname(ename); emp.setJob_id(job_id); emp.setMgr(mgr); emp.setJoindate(joindate); emp.setSalary(salary); emp.setBonus(bonus); emp.setDept_id(dept_id); return emp; } }); for (Emp emp : list) { System.out.println(emp); } } /** * 6. 查询所有记录,将其封装为Emp对象的List集合 */ @Test public void test6_2(){ String sql = "select * from emp"; List<Emp> list = template.query(sql, new BeanPropertyRowMapper<Emp>(Emp.class)); for (Emp emp : list) { System.out.println(emp); } } /** * 7. 查询总记录数 */ @Test public void test7(){ String sql = "select count(id) from emp"; Long total = template.queryForObject(sql, Long.class); System.out.println(total); } }
    Processed: 0.012, SQL: 8