JDBC
    1、JDBC是什么?
    Java DataBase Connectivity(Java语言连接数据库)
    2、JDBC的本质是什么?
    JDBC是SUN公司制定的一套接口(interface)
    java.sql.*; (这个软件包下有很多接口。)
    接口都有调用者和实现者。
    面向接口调用、面向接口写实现类,这都属于面向接口编程。
    为什么要面向接口编程?
    解耦合:降低程序的耦合度,提高程序的扩展力。
    多态机制就是非常典型的:面向抽象编程。(不要面向具体编程)
    建议:
    Animal a = new Cat();
    Animal a = new Dog();
    // 喂养的方法
    public void feed(Animal a){ // 面向父类型编程。

    }
    不建议:
    Dog d = new Dog();
    Cat c = new Cat();

    思考:为什么SUN制定一套JDBC接口呢?
    因为每一个数据库的底层实现原理都不一样。
    Oracle数据库有自己的原理。
    MySQL数据库也有自己的原理。
    MS SqlServer数据库也有自己的原理。
    ….
    每一个数据库产品都有自己独特的实现原理。

    JDBC的本质到底是什么?
    一套接口。
    3、JDBC开发前的准备工作,先从官网下载对应的驱动jar包,然后将其配置到环境变量classpath当中。
    classpath=.;D:\course\06-JDBC\resources\MySql Connector Java 5.1.23\mysql-connector-java-5.1.23-bin.jar
    以上的配置是针对于文本编辑器的方式开发,使用IDEA工具的时候,不需要配置以上的环境变量。
    IDEA有自己的配置方式。

    4、JDBC编程六步(需要背会)

    第一步:注册驱动(作用:告诉Java程序,即将要连接的是哪个品牌的数据库)
    第二步:获取连接(表示JVM的进程和数据库进程之间的通道打开了,这属于进程之间的通信,重量级的,使用完之后一定要关闭通道。)
    第三步:获取数据库操作对象(专门执行sql语句的对象)
    第四步:执行SQL语句(DQL DML….)
    第五步:处理查询结果集(只有当第四步执行的是select语句的时候,才有这第五步处理查询结果集。)
    第六步:释放资源(使用完资源之后一定要关闭资源。Java和数据库属于进程间的通信,开启之后一定要关闭。)

    1. import java.sql.*;
    2. public class JDBCTest01 {
    3. public static void main(String[] args) {
    4. Connection conn = null;
    5. Statement stmt = null;
    6. try{
    7. //1. 注册驱动
    8. Driver driver = new com.mysql.cj.jdbc.Driver();//多态,父类型引用指向子类型对象
    9. DriverManager.registerDriver(driver);
    10. //2. 获取连接
    11. /*
    12. url:统一资源定位符(网络资源绝对路径)
    13. 包括:
    14. http://36.152.44.95:80/index.html
    15. 协议 IP port 资源名
    16. */
    17. String url = "jdbc:mysql://127.0.0.1:3306/bjpowernode?serverTimezone=GMT";
    18. //localhost和 127.0.0.1都是本机IP
    19. String user = "root";
    20. String password = "hqw3.1415926";
    21. conn = DriverManager.getConnection(url,user,password);
    22. System.out.println("数据库连接对象=" + conn);
    23. //3. 获取数据库操作对象(Statement专门执行sql)
    24. stmt = conn.createStatement();
    25. //4. 执行sql
    26. String sql = "insert into dept(deptno,dname,loc) values(50,'人事部','北京')";
    27. //专门执行DML语句的(insert delete update)
    28. //返回值时影响数据库的记录条数
    29. int count = stmt.executeUpdate(sql);
    30. System.out.println(count ==1 ? "保存成功":"保存失败");
    31. //5. 处理查询结果集
    32. }catch (SQLException e){
    33. e.printStackTrace();
    34. }finally{
    35. //6. 释放资源
    36. //未来保证资源释放,在语句块中关闭资源
    37. //并且从小到大依次关闭
    38. if(stmt!= null){
    39. try {
    40. stmt.close();
    41. } catch (SQLException t) {
    42. t.printStackTrace();
    43. }
    44. }
    45. if (conn != null){
    46. try {
    47. conn.close();
    48. } catch (SQLException t) {
    49. t.printStackTrace();
    50. }
    51. }
    52. }
    53. }
    54. }
    1. import java.sql.Connection;
    2. import java.sql.DriverManager;
    3. import java.sql.SQLException;
    4. import java.sql.Statement;
    5. public class JDBCTest02 {
    6. public static void main(String[] args) {
    7. Connection conn = null;
    8. Statement stat = null;
    9. try{
    10. //1.注册驱动
    11. DriverManager.registerDriver(new com.mysql.cj.jdbc.Driver());
    12. //2.获取连接
    13. conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/bjpowernode?serverTimezone=GMT","root","hqw3.1415926");
    14. //3.获取数据库操作对象
    15. stat = conn.createStatement();
    16. //4.执行SQL语句
    17. //java中sql语句不写分号
    18. String sql = "delete from dept where deptno = 50";
    19. int count = stat.executeUpdate(sql);
    20. System.out.println(count == 1 ? "删除成功" : "删除失败");
    21. }catch (SQLException e){
    22. e.printStackTrace();
    23. }finally{
    24. //5.释放连接
    25. if (stat != null){
    26. try {
    27. stat.close();
    28. } catch (SQLException throwables) {
    29. throwables.printStackTrace();
    30. }
    31. }
    32. if (conn != null){
    33. try {
    34. conn.close();
    35. } catch (SQLException throwables) {
    36. throwables.printStackTrace();
    37. }
    38. }
    39. }
    40. }
    41. }
    1. import java.sql.Connection;
    2. import java.sql.DriverManager;
    3. import java.sql.SQLException;
    4. import java.sql.Statement;
    5. import java.util.ResourceBundle;
    6. public class JDBCTest03 {
    7. public static void main(String[] args) {
    8. //使用资源绑定器绑定属性配置文件
    9. ResourceBundle bundle = ResourceBundle.getBundle("jdbc");
    10. String driver = bundle.getString("driver");
    11. String url = bundle.getString("url");
    12. String user = bundle.getString("user");
    13. String password = bundle.getString("password");
    14. Connection conn = null;
    15. Statement stat = null;
    16. try {
    17. //1.注册驱动
    18. //第一种方法:DriverManager.registerDriver(new com.mysql.cj.jdbc.Driver());
    19. //第二种常用:
    20. Class.forName(driver);
    21. //2.获取连接
    22. conn = DriverManager.getConnection(url,user,password);
    23. //3.获取数据库操作对象
    24. stat = conn.createStatement();
    25. //4.执行SQL语句
    26. String sql = "insert into dept(deptno,dname,loc) values(50,'人事部','北京')";
    27. //专门执行DML语句的(insert delete update)
    28. //返回值时影响数据库的记录条数
    29. int count = stat.executeUpdate(sql);
    30. System.out.println(count ==1 ? "保存成功":"保存失败");
    31. } catch (SQLException e) {
    32. e.printStackTrace();
    33. } catch (ClassNotFoundException e) {
    34. e.printStackTrace();
    35. }
    36. }
    37. }
    • 模拟用户登录功能 ```java import java.sql.*; import java.util.HashMap; import java.util.Map; import java.util.Scanner;

    public class JDBCTest06 { public static void main(String[] args) { //初始化一个界面 Map userLoginInfo = initUI(); //验证用户名和密码 boolean loginSuccess = login(userLoginInfo); //输出结果 System.out.println((loginSuccess ? “登录成功” : “登录失败”)); }

    1. /**
    2. * 用户登录
    3. * @param userLoginInfo 用户登录信息
    4. * @return false表示失败 true成功
    5. */
    6. private static boolean login(Map<String, String> userLoginInfo) {
    7. //打标记
    8. boolean loginSuccess = false;
    9. //单独定义变量
    10. String loginName = userLoginInfo.get("loginName");
    11. String loginPwd = userLoginInfo.get("loginPwd");
    12. //JDBC代码
    13. Connection conn = null;
    14. Statement stmt = null;
    15. ResultSet rs = null;
    16. try {
    17. //1.注册驱动
    18. Class.forName("com.mysql.cj.jdbc.Driver");
    19. //2.获取连接
    20. conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/bjpowernode?serverTimezone=GMT","root","hqw3.1415926");
    21. //3.获取数据操作对象
    22. stmt = conn.createStatement();
    23. //4.执行sql
    24. String sql = "select * from t_user where loginName = '"+loginName+"' and loginPwd = '"+loginPwd+"' ";
    25. rs = stmt.executeQuery(sql);
    26. //5.处理结果集
    27. if (rs.next()){
    28. //登录成功
    29. loginSuccess = true;
    30. }
    31. } catch (ClassNotFoundException e) {
    32. e.printStackTrace();
    33. } catch (SQLException throwables) {
    34. throwables.printStackTrace();
    35. } finally {
    36. //6.释放资源
    37. if (rs != null){
    38. try {
    39. rs.close();
    40. } catch (SQLException throwables) {
    41. throwables.printStackTrace();
    42. }
    43. }
    44. if (stmt != null){
    45. try {
    46. stmt.close();
    47. } catch (SQLException throwables) {
    48. throwables.printStackTrace();
    49. }
    50. }
    51. if (conn != null){
    52. try {
    53. conn.close();
    54. } catch (SQLException throwables) {
    55. throwables.printStackTrace();
    56. }
    57. }
    58. }
    59. return loginSuccess;
    60. }
    61. /**
    62. * 初始化用户信息
    63. * @return 用户输入用户名和密码登录信息
    64. */
    65. private static Map<String,String> initUI() {
    66. Scanner s = new Scanner(System.in);
    67. System.out.println("用户名:");
    68. String loginName = s.nextLine();
    69. System.out.println("密码:");
    70. String loginPwd = s.nextLine();
    71. Map<String,String> userLoginInfo = new HashMap<>();
    72. userLoginInfo.put("loginName",loginName);
    73. userLoginInfo.put("loginPwd",loginPwd);
    74. return userLoginInfo;
    75. }

    }

    1. **上面案例存在sql注入**<br />用户输入信息含有sql关键字,并且这些关键字参与sql语句编译,导致sql语句的原意被扭曲,进而达到sql注入<br />解决sql注入:
    2. - PreparedStatement接口继承了java.sql.Statement,是属于预编译的数据库对象。原理是对sql框架预编译
    3. - PreparedStatement编译一次执行n
    4. - PreparedStatement会在编译阶段做类型的安全检查
    5. ```java
    6. public class JDBCTest07 {
    7. public static void main(String[] args) {
    8. //初始化一个界面
    9. Map<String,String> userLoginInfo = initUI();
    10. //验证用户名和密码
    11. boolean loginSuccess = login(userLoginInfo);
    12. //输出结果
    13. System.out.println((loginSuccess ? "登录成功" : "登录失败"));
    14. }
    15. /**
    16. * 用户登录
    17. * @param userLoginInfo 用户登录信息
    18. * @return false表示失败 true成功
    19. */
    20. private static boolean login(Map<String, String> userLoginInfo) {
    21. //打标记
    22. boolean loginSuccess = false;
    23. //单独定义变量
    24. String loginName = userLoginInfo.get("loginName");
    25. String loginPwd = userLoginInfo.get("loginPwd");
    26. //JDBC代码
    27. Connection conn = null;
    28. PreparedStatement ps = null;
    29. ResultSet rs = null;
    30. try {
    31. //1.注册驱动
    32. Class.forName("com.mysql.cj.jdbc.Driver");
    33. //2.获取连接
    34. conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/bjpowernode?serverTimezone=GMT","root","hqw3.1415926");
    35. //3.获取预编译的数据操作对象
    36. //问号为占位符,?将来接收一个值
    37. String sql = "select * from t_user where loginName = ? and loginPwd = ?";
    38. //sql语句发给DBMS进行预编译
    39. ps = conn.prepareStatement(sql);
    40. //给占位符传值(第一个?下标为1,JDBC下标从1开始)
    41. ps.setString(1,loginName);
    42. ps.setString(2,loginPwd);
    43. //4.执行sql
    44. rs = ps.executeQuery();
    45. //5.处理结果集
    46. if (rs.next()){
    47. //登录成功
    48. loginSuccess = true;
    49. }
    50. } catch (ClassNotFoundException e) {
    51. e.printStackTrace();
    52. } catch (SQLException throwables) {
    53. throwables.printStackTrace();
    54. } finally {
    55. //6.释放资源
    56. if (rs != null){
    57. try {
    58. rs.close();
    59. } catch (SQLException throwables) {
    60. throwables.printStackTrace();
    61. }
    62. }
    63. if (ps != null){
    64. try {
    65. ps.close();
    66. } catch (SQLException throwables) {
    67. throwables.printStackTrace();
    68. }
    69. }
    70. if (conn != null){
    71. try {
    72. conn.close();
    73. } catch (SQLException throwables) {
    74. throwables.printStackTrace();
    75. }
    76. }
    77. }
    78. return loginSuccess;
    79. }
    80. /**
    81. * 初始化用户信息
    82. * @return 用户输入用户名和密码登录信息
    83. */
    84. private static Map<String,String> initUI() {
    85. Scanner s = new Scanner(System.in);
    86. System.out.println("用户名:");
    87. String loginName = s.nextLine();
    88. System.out.println("密码:");
    89. String loginPwd = s.nextLine();
    90. Map<String,String> userLoginInfo = new HashMap<>();
    91. userLoginInfo.put("loginName",loginName);
    92. userLoginInfo.put("loginPwd",loginPwd);
    93. return userLoginInfo;
    94. }
    95. }
    1. import java.sql.Connection;
    2. import java.sql.DriverManager;
    3. import java.sql.PreparedStatement;
    4. import java.sql.SQLException;
    5. public class JDBCTest09 {
    6. public static void main(String[] args) {
    7. Connection conn = null;
    8. PreparedStatement ps = null;
    9. try {
    10. //注册驱动
    11. Class.forName("com.mysql.cj.jdbc.Driver");
    12. //获取连接
    13. conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/bjpowernode?serverTimezone=GMT","root","hqw3.1415926");
    14. //获取预编译的数据库对象
    15. String sql = "insert into dept(deptno,dname,loc) values (?,?,?)";
    16. ps = conn.prepareStatement(sql);
    17. ps.setInt(1,60);
    18. ps.setString(2,"销售部");
    19. ps.setString(3,"上海");
    20. //执行sql
    21. int count = ps.executeUpdate();
    22. System.out.println(count);
    23. } catch (ClassNotFoundException e) {
    24. e.printStackTrace();
    25. } catch (SQLException throwables) {
    26. throwables.printStackTrace();
    27. } finally {
    28. if (ps != null){
    29. try {
    30. ps.close();
    31. } catch (SQLException throwables) {
    32. throwables.printStackTrace();
    33. }
    34. }
    35. if (conn != null){
    36. try {
    37. conn.close();
    38. } catch (SQLException throwables) {
    39. throwables.printStackTrace();
    40. }
    41. }
    42. }
    43. }
    44. }
    • JDBC事务机制

    JDBC中只要完成一个DML语句就提交一次

    1. import java.sql.Connection;
    2. import java.sql.DriverManager;
    3. import java.sql.PreparedStatement;
    4. import java.sql.SQLException;
    5. /**
    6. * sql脚本:
    7. * drop table if exists t_act;
    8. * create table t_act(
    9. * actno bigint,
    10. * balance double(7,2)
    11. * );
    12. * insert into t_act(actno,balance) values (111,20000);
    13. * insert into t_act(actno,balance) values (222,0);
    14. * commit;
    15. * select * from t_act;
    16. */
    17. public class JDBCTest10 {
    18. public static void main(String[] args) {
    19. Connection conn = null;
    20. PreparedStatement ps = null;
    21. try {
    22. Class.forName("com.mysql.cj.jdbc.Driver");
    23. conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/bjpowernode","root","hqw3.1415926");
    24. //将自动提交机制调整为手动提交,开启事务
    25. conn.setAutoCommit(false);
    26. String sql = "update t_act set balance = ? where actno = ?";
    27. ps = conn.prepareStatement(sql);
    28. ps.setDouble(1,10000);
    29. ps.setDouble(2,111);
    30. int count = ps.executeUpdate();
    31. ps.setDouble(1,10000);
    32. ps.setDouble(2,222);
    33. count += ps.executeUpdate();
    34. System.out.println(count ==2 ? "转账成功" : "转账失败");
    35. //程序能走到这说明没有异常,事务结束,手动提交
    36. conn.commit();
    37. } catch (ClassNotFoundException e) {
    38. //回滚事务
    39. if (conn != null) {
    40. try {
    41. conn.rollback();
    42. } catch (SQLException throwables) {
    43. throwables.printStackTrace();
    44. }
    45. }
    46. e.printStackTrace();
    47. } catch (SQLException throwables) {
    48. throwables.printStackTrace();
    49. } finally {
    50. if (ps != null){
    51. try {
    52. ps.close();
    53. } catch (SQLException throwables) {
    54. throwables.printStackTrace();
    55. }
    56. }
    57. if (conn != null){
    58. try {
    59. conn.close();
    60. } catch (SQLException throwables) {
    61. throwables.printStackTrace();
    62. }
    63. }
    64. }
    65. }
    66. }

    自建工具类并实现模糊查询

    1. import java.sql.*;
    2. public class DBUtil {
    3. /**
    4. * 工具类中的构造方法都是私有的
    5. * 因为工具类中的方法是静态的,不需要new对象,直接采用类名调用
    6. */
    7. private DBUtil(){}
    8. //静态代码块在类加载时只执行一次
    9. static {
    10. try {
    11. Class.forName("com.mysql.cj.jdbc.Driver");
    12. } catch (ClassNotFoundException e) {
    13. e.printStackTrace();
    14. }
    15. }
    16. /**
    17. * 获取数据库连接对象
    18. * @return 连接对象
    19. * @throws SQLException
    20. */
    21. public static Connection getConnection() throws SQLException {
    22. return DriverManager.getConnection("jdbc:mysql://localhost:3306/bjpowernode?serverTimezone=GMT","root","hqw3.1415926");
    23. }
    24. /**
    25. * 关闭资源
    26. * @param conn 连接对象
    27. * @param ps 数据库操作对象
    28. * @param rs 结果集
    29. */
    30. public static void close(Connection conn, Statement ps, ResultSet rs){
    31. if (rs != null){
    32. try {
    33. rs.close();
    34. } catch (SQLException throwables) {
    35. throwables.printStackTrace();
    36. }
    37. }
    38. if (ps != null){
    39. try {
    40. ps.close();
    41. } catch (SQLException throwables) {
    42. throwables.printStackTrace();
    43. }
    44. }
    45. if (conn != null){
    46. try {
    47. conn.close();
    48. } catch (SQLException throwables) {
    49. throwables.printStackTrace();
    50. }
    51. }
    52. }
    53. }
    1. import java.sql.Connection;
    2. import java.sql.PreparedStatement;
    3. import java.sql.ResultSet;
    4. import java.sql.SQLException;
    5. public class JDBCTest12 {
    6. public static void main(String[] args) {
    7. Connection conn = null;
    8. PreparedStatement ps = null;
    9. ResultSet rs = null;
    10. try {
    11. //获取连接
    12. conn = DBUtil.getConnection();
    13. //获取预编译的数据库操作对象
    14. /*
    15. String sql = "select ename from emp where ename like '_?%'";
    16. ps = conn.prepareStatement(sql);
    17. ps.setString(1,"A");
    18. 错误写法
    19. */
    20. String sql = "select ename from emp where ename like ?";
    21. ps = conn.prepareStatement(sql);
    22. ps.setString(1,"_A%");
    23. rs = ps.executeQuery();
    24. while (rs.next()){
    25. System.out.println(rs.getString("ename"));
    26. }
    27. } catch (SQLException throwables) {
    28. throwables.printStackTrace();
    29. } finally{
    30. DBUtil.close(conn,ps,rs);
    31. }
    32. }
    33. }