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的本质到底是什么?
    JDBC本质.jpg
    一套接口。
    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. package com.zxx.jdbc;
    2. import java.sql.Connection;
    3. import java.sql.DriverManager;
    4. import java.sql.SQLException;
    5. import java.sql.Statement;
    6. import java.util.ResourceBundle;
    7. public class JDBCTest01 {
    8. public static void main(String[] args) {
    9. Connection connection=null;
    10. Statement statement= null;
    11. //使用资源绑定器绑定属性配置文件
    12. ResourceBundle bundle =ResourceBundle.getBundle("jdbc");
    13. String url =bundle.getString("url");
    14. String user=bundle.getString("user");
    15. String password=bundle.getString("password");
    16. try {
    17. //1.类加载执行静态代码块,获取数据库驱动
    18. Class.forName("com.mysql.jdbc.Driver");
    19. //2.获取数据库连接
    20. connection= DriverManager.getConnection(url,user,password);
    21. //3.获取数据库操作对象
    22. statement = connection.createStatement();
    23. //4.执行sql
    24. String sql="delete from emp where empno=7902 ";
    25. int i = statement.executeUpdate(sql);
    26. System.out.println(i);
    27. } catch (ClassNotFoundException e) {
    28. e.printStackTrace();
    29. } catch (SQLException e) {
    30. e.printStackTrace();
    31. }
    32. finally {
    33. //5.关闭流
    34. if (statement!=null){
    35. try {
    36. statement.close();
    37. } catch (SQLException e) {
    38. e.printStackTrace();
    39. }
    40. }
    41. if (connection!=null){
    42. try {
    43. connection.close();
    44. } catch (SQLException e) {
    45. e.printStackTrace();
    46. }
    47. }
    48. }
    49. }
    50. }
    1. //jdbc.properties
    2. url=jdbc:mysql://localhost:3306/bjpowernode
    3. user=root
    4. password=root
    1. package com.zxx.jdbc;
    2. import java.sql.*;
    3. import java.util.ResourceBundle;
    4. public class JDBCTest01 {
    5. public static void main(String[] args) {
    6. Connection connection=null;
    7. Statement statement= null;
    8. //使用资源绑定器绑定属性配置文件
    9. ResourceBundle bundle =ResourceBundle.getBundle("jdbc");
    10. String url =bundle.getString("url");
    11. String user=bundle.getString("user");
    12. String password=bundle.getString("password");
    13. try {
    14. Class.forName("com.mysql.jdbc.Driver");
    15. connection= DriverManager.getConnection(url,user,password);
    16. statement = connection.createStatement();
    17. String sql="select * from dept";
    18. ResultSet resultSet = statement.executeQuery(sql);
    19. //遍历结果集
    20. while (resultSet.next()){
    21. //取第一个元素的数据
    22. int deptno1= resultSet.getInt(1);
    23. //取列名为dept的元素,更加精准,推荐使用
    24. int deptno2= resultSet.getInt("deptno");
    25. System.out.println(deptno1);
    26. System.out.println(deptno2);
    27. }
    28. } catch (ClassNotFoundException e) {
    29. e.printStackTrace();
    30. } catch (SQLException e) {
    31. e.printStackTrace();
    32. }
    33. finally {
    34. if (statement!=null){
    35. try {
    36. statement.close();
    37. } catch (SQLException e) {
    38. e.printStackTrace();
    39. }
    40. }
    41. if (connection!=null){
    42. try {
    43. connection.close();
    44. } catch (SQLException e) {
    45. e.printStackTrace();
    46. }
    47. }
    48. }
    49. }
    50. }

    使用idea创建数据库驱动
    1.首先先创建一个空的project
    2020-11-27_174259.png

    2.创建一个空的java模块
    2020-11-27_174331.png
    3.选择以下选项
    2020-11-27_174451.png
    4.导入mysql驱动的jar包
    2020-11-27_174602.png

    用statement时会引发sql注入的问题

    1. package com.zxx.jdbc;
    2. import java.sql.*;
    3. import java.util.HashMap;
    4. import java.util.Map;
    5. import java.util.Scanner;
    6. public class JDBCTest02 {
    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 true 登录成功,false 登录失败
    19. */
    20. private static boolean login(Map<String, String> userLoginInfo) {
    21. //JDBC代码
    22. Connection connection=null;
    23. Statement statement=null;
    24. ResultSet resultSet=null;
    25. boolean state=false;
    26. //1.获取数据库驱动
    27. try {
    28. Class.forName("com.mysql.jdbc.Driver");
    29. //2.获取数据库连接
    30. connection= DriverManager.getConnection("jdbc:mysql://localhost:3306/bjpowernode","root","root");
    31. //3.创建数据库操作对象
    32. statement =connection.createStatement();
    33. //4.执行sql
    34. //在输入密码fs' or '1'='1会引发sql注入的问题
    35. String sql ="select * from t_user where lgoinName='"+userLoginInfo.get("loginName")+"' and loginPassword='"+userLoginInfo.get("loginPassword")+"'";
    36. resultSet = statement.executeQuery(sql);
    37. //5.处理结果集
    38. if (resultSet.next()){
    39. state=true;
    40. }
    41. } catch (ClassNotFoundException e) {
    42. e.printStackTrace();
    43. } catch (SQLException e) {
    44. e.printStackTrace();
    45. }
    46. finally {
    47. //6.关闭流
    48. if (resultSet!=null){
    49. try {
    50. resultSet.close();
    51. } catch (SQLException e) {
    52. e.printStackTrace();
    53. }
    54. }
    55. if (statement!=null){
    56. try {
    57. statement.close();
    58. } catch (SQLException e) {
    59. e.printStackTrace();
    60. }
    61. }
    62. if (connection!=null){
    63. try {
    64. connection.close();
    65. } catch (SQLException e) {
    66. e.printStackTrace();
    67. }
    68. }
    69. }
    70. return state;
    71. }
    72. /**
    73. * 初始化用户界面
    74. * @return 用户输入的用户名和密码等登录信息
    75. */
    76. private static Map<String, String> initUI() {
    77. Scanner scanner=new Scanner(System.in);
    78. System.out.println("用户名");
    79. String loginName=scanner.nextLine();
    80. System.out.println("密码");
    81. String loginPassword=scanner.nextLine();
    82. Map<String,String> userLoginInfo=new HashMap<>();
    83. userLoginInfo.put("loginName",loginName);
    84. userLoginInfo.put("loginPassword",loginPassword);
    85. return userLoginInfo;
    86. }
    87. }

    解决sql注入

    1. package com.zxx.jdbc;
    2. import java.sql.*;
    3. import java.util.HashMap;
    4. import java.util.Map;
    5. import java.util.Scanner;
    6. public class JDBCTest02 {
    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 true 登录成功,false 登录失败
    19. */
    20. private static boolean login(Map<String, String> userLoginInfo) {
    21. //JDBC代码
    22. Connection connection=null;
    23. PreparedStatement statement=null;
    24. ResultSet resultSet=null;
    25. boolean state=false;
    26. //1.获取数据库驱动
    27. try {
    28. Class.forName("com.mysql.jdbc.Driver");
    29. //2.获取数据库连接
    30. connection= DriverManager.getConnection("jdbc:mysql://localhost:3306/bjpowernode","root","root");
    31. //3.创建预编译的数据库操作对象
    32. //在编译前定好sql语句的格式
    33. String sql ="select * from t_user where lgoinName=? and loginPassword=?";
    34. //程序执行到此处,会发送sql语句框子给DBMS 然后DBMS进行sql语句的预先编译
    35. statement=connection.prepareStatement(sql);
    36. //给占位符?传值 第一个问号下标是1 第二个问号下标是2
    37. statement.setString(1,userLoginInfo.get("loginName"));
    38. statement.setString(2,userLoginInfo.get("loginPassword"));
    39. //4.执行sql
    40. resultSet = statement.executeQuery();
    41. //5.处理结果集
    42. if (resultSet.next()){
    43. state=true;
    44. }
    45. } catch (ClassNotFoundException e) {
    46. e.printStackTrace();
    47. } catch (SQLException e) {
    48. e.printStackTrace();
    49. }
    50. finally {
    51. //6.关闭流
    52. if (resultSet!=null){
    53. try {
    54. resultSet.close();
    55. } catch (SQLException e) {
    56. e.printStackTrace();
    57. }
    58. }
    59. if (statement!=null){
    60. try {
    61. statement.close();
    62. } catch (SQLException e) {
    63. e.printStackTrace();
    64. }
    65. }
    66. if (connection!=null){
    67. try {
    68. connection.close();
    69. } catch (SQLException e) {
    70. e.printStackTrace();
    71. }
    72. }
    73. }
    74. return state;
    75. }
    76. /**
    77. * 初始化用户界面
    78. * @return 用户输入的用户名和密码等登录信息
    79. */
    80. private static Map<String, String> initUI() {
    81. Scanner scanner=new Scanner(System.in);
    82. System.out.println("用户名");
    83. String loginName=scanner.nextLine();
    84. System.out.println("密码");
    85. String loginPassword=scanner.nextLine();
    86. Map<String,String> userLoginInfo=new HashMap<>();
    87. userLoginInfo.put("loginName",loginName);
    88. userLoginInfo.put("loginPassword",loginPassword);
    89. return userLoginInfo;
    90. }
    91. }

    解决sql注入的关键:用户提供的信息中含有sql关键字,但是这些关键字并没有参与编译 不起作用

    statement和preparestatement的区别
    前者存在sql注入
    前者编译一次执行一次 后者编译一次 可执行多次 效率更高
    后者会在编译阶段进行安全检查
    当业务要求sql注入时才会使用前者

    jdbc的事务是自动提交的 每执行一条sql语句 就会提交一次 而具体业务有多条sql
    重点三行代码

    conn.setAutoCommit(false) 关闭自动提交 改为手动
    conn.commit()提交
    conn.rollback()回滚
    悲观锁(行级锁for update)和乐观锁机制.jpg