今日内容
  • 基本概念
  • 快速入门
  • 对JDBC中各个接口和类的详解
一、基本概念
1.概念:Java Database Connectivity:Java数据库连接,Java语言操作数据库
2.本质:官方(Sun)定义的一套操作所有关系型数据库的规则,即接口。各个数据库厂商实现这套接口,提供数据库驱动jar包,我们可以使用这套接口(JDBC)编程,真正执行的代码是jar包中的实现类
即:JDBC是接口,真正执行的是jar包中的实现类
SUN公司写的代码,定义了一套操作所有关系型数据库的规则(接口),没有定义实现类,实现类由不同数据库厂商写出对应数据库的实现类(数据库驱动),不同实现类可以操作自己的数据库。
                                                                                            以接口类型调用方法,真正执行的是实现方法
例如 interface Person              class Worker                     Person p=new Work();             p.eat();多态调用
3.快速入门
  • 步骤【创建空项目project,新建模块module,模块module就放到了项目下】
    • 导入驱动jar包mysql-connector-java-5.1.37-bin.jar
      • 复制mysql-connector-java-5.1.37-bin.jar到项目的libs目录下
      • 右键-->add as library
jar包内是一些已经编译好的class字节码文件
src是开源的源码文件
    • 注册驱动
    • 获取数据库的连接对象Connection(java和数据库的桥梁对象)
    • 定义SQL语句
    • 获取执行SQL语句的对象Statement
    • 执行SQL,接收返回的结果
    • 处理结果
    • 释放资源,不释放容易造成内存的泄露问题
  • 使用
    • 创建一个项目Project---itcast
    • 在项目的project structure创建一个新module---day04_jdbc
  1. package cn.itcast.jdbc;
  2. import java.sql.Connection;
  3. import java.sql.DriverManager;
  4. import java.sql.Statement;
  5. /**
  6. * JDBC快速入门
  7. */
  8. public class JdbcDemo1 {
  9. public static void main(String[] args) throws Exception{
  10. //1.导入驱动jar包mysql-connector-java-5.1.37-bin.jar
  11. //创建libs文件夹便于管理
  12. //复制后右键,add as library
  13. //2.注册驱动
  14. Class.forName("com.mysql.jdbc.Driver");
  15. //3.获取数据库的连接对象
  16. Connection conn= DriverManager.getConnection("jdbc:mysql://localhost:3306/db3","root","root");
  17. //4.定义一个SQL语句
  18. String sql="update account set balance = 500 where id=1";//sql语句后不用加分号
  19. //5.获取SQL的执行对象
  20. Statement stmt = conn.createStatement();
  21. //6.执行SQL
  22. int count = stmt.executeUpdate(sql);
  23. //7.处理结果,打印
  24. System.out.println(count);
  25. //8.释放资源
  26. stmt.close();
  27. conn.close();
  28. }
  29. }
二、各个对象的详解
常见对象
  • DriverManager--驱动管理对象
  • Connection--数据库连接对象
  • Statement--执行SQL的对象

  • ResultSet--结果集对象
  • PreparedStatement--预编译SQL对象
1.JDBC各个类详解_DriverManager_注册驱动
可以实现注册驱动和获取数据库连接
数据库驱动管理类的功能:
  • 注册驱动Class.forName("com.mysql.jdbc.Driver");
    • 代码是这么写的Class.forName("com.mysql.jdbc.Driver");把字节码文件加载进内存【这样简单,实际上还是用了DriverManager
    • 实际上DriverManager有注册驱动的方法   static void registerDriver(Driver driver) 使用 DriverManager注册给定的驱动程序。
    • 二者的区别:上者中有一些代码会随着类执行(静态代码块
    • 通过查看源码发现,在mom.mysql.jdbc.Driver中存在静态代码块:
  1. static {
  2. try {
  3. java.sql.DriverManager.registerDriver(new Driver());
  4. } catch (SQLException E) {
  5. throw new RuntimeException("Can't register driver!");
  6. }
  7. }
注意:
        在mysql5之后的驱动jar包,注册驱动的代码可以省略,注释Class.forName("com.mysql.jdbc.Driver");

MySQL5之后的驱动jar包可以省略注册驱动的步骤
  • 获取数据库连接 Connection conn= DriverManager.getConnection("jdbc:mysql://localhost:3306/db3","root","root");
    • static Connection getConnection(String url, String user, String password) 尝试建立与给定数据库URL的连接。
    • url:指定连接的l路径
      • 语法:(MySQL)-jdbc:mysql:-//ip地址:端口/数据库名
      • 例子:jdbc:mysql://localhost:3306/db3
      • 细节:如果连接的是本机的MySQL服务器,并且默认端口是3306,则可以简写为jdbc:mysql///数据库名
  1. package cn.itcast.jdbc;
  2. import java.sql.Connection;
  3. import java.sql.DriverManager;
  4. import java.sql.Statement;
  5. public class Jdbc_demo1 {
  6. public static void main(String[] args) throws Exception{
  7. //1.导入驱动jar包mysql-connector-java-5.1.37-bin.jar
  8. //创建libs文件夹便于管理
  9. //复制后右键,add as library
  10. //2.注册驱动
  11. //Class.forName("com.mysql.jdbc.Driver");
  12. //3.获取数据库的连接对象
  13. Connection conn= DriverManager.getConnection("jdbc:mysql:///db3","root","root");
  14. //4.定义一个SQL语句
  15. String sql="update account set balance = 2000 where id=1";//sql语句后不用加分号
  16. //5.获取SQL的执行对象
  17. Statement stmt = conn.createStatement();
  18. //6.执行SQL
  19. int count = stmt.executeUpdate(sql);
  20. //7.处理结果,打印
  21. System.out.println(count);
  22. //8.释放资源
  23. stmt.close();
  24. conn.close();
  25. }
  26. }
2.JDBC各个类详解_Connection
可以获取执行SQL的对象并可以实现事务的管理
数据库和Java之间的桥梁
2.1功能
  • 获取执行SQL的对象Statement stmt = conn.createStatement();
Statement createStatement() 创建一个 Statement对象,用于将SQL语句发送到数据库。  
PreparedStatement prepareStatement(String sql) 创建一个 PreparedStatement对象,用于将参数化的SQL语句发送到数据库。  
  • 管理事务
    • 事务:多个步骤的业务操作,要么同时成功,要么同时失败
    • 三个方法--开启事务:void setAutoCommit(boolean autoCommit) 调用此方法设置false,即开启事务并不自动提交
    • 三个方法--提交事务:void commit() 提交事务
    • 三个方法--回滚事务:void rollback() 回滚事务
3.JDBC各个类详解_Statement
执行SQL的对象
参数的值是给定的
3.1 常用的方法
  • boolean execute() 可以执行任意的SQL,了解
  • true如果第一个结果是一个ResultSet对象; false如果第一个结果是更新计数或没有结果
  • int executeUpdate() 可以执行DML(insert update delete对表中数据进行修改)语句、DDL(对表和库进行修改,create、alter、drop,不常用,dba用SQL设置好)语句
  • (1)SQL数据操作语言(DML)语句的行计数或(2)0不返回的SQL语句 
    如update account set balance =1000;//返回影响的行数
    可以通过影响的行数判断DML是否执行成功,如果大于0,则执行成功,反之则失败
  • ResultSet executeQuery(String sql) :执行DQL(select)语句,返回ResultSet
  • 先学习update增删改,再学习select
3.2 Statement--JDBC练习_insert语句执行增删改
之前代码不规范,释放资源应该放入finally内部,不管是否执行成功都要释放资源
练习
  • 为account表添加一条记录
  1. package cn.itcast.jdbc;
  2. import java.sql.Connection;
  3. import java.sql.DriverManager;
  4. import java.sql.SQLException;
  5. import java.sql.Statement;
  6. /**
  7. * account表,添加一条记录 insert语句
  8. */
  9. public class Jdbc_demo2 {
  10. public static void main(String[] args){
  11. Statement stmt=null;
  12. Connection conn= null;
  13. try {
  14. //1.注册驱动
  15. Class.forName("com.mysql.jdbc.Driver");
  16. //定义sql语句
  17. String sql="insert into account values(null,'wangwu',3000)";
  18. //3.获取Connection对象
  19. conn = DriverManager.getConnection("jdbc:mysql:///db3", "root", "root");
  20. // 有异常 ,alt+enter
  21. //4.获取执行sql的对象 Statement
  22. stmt = conn.createStatement();
  23. //5.执行sql
  24. int count = stmt.executeUpdate(sql);//影响的行数
  25. //6.处理结果
  26. System.out.println(count);
  27. if (count>0){
  28. System.out.println("添加成功");
  29. }else
  30. System.out.println("添加失败");
  31. } catch (ClassNotFoundException e) {
  32. e.printStackTrace();
  33. } catch (SQLException e) {
  34. e.printStackTrace();
  35. }finally {
  36. //7.释放资源
  37. //先释放Statement对象,是由connection获取的
  38. //stmt.close();//作用域不同
  39. //为了避免空指针异常,判断是否为null
  40. if (stmt!= null){
  41. try {
  42. stmt.close();
  43. } catch (SQLException e) {
  44. e.printStackTrace();
  45. }
  46. }
  47. //释放conn
  48. if (conn!= null){
  49. try {
  50. conn.close();
  51. } catch (SQLException e) {
  52. e.printStackTrace();
  53. }
  54. }
  55. }
  56. }
  57. }
  • account表修改记录
  1. package cn.itcast.jdbc;
  2. import java.sql.Connection;
  3. import java.sql.DriverManager;
  4. import java.sql.SQLException;
  5. import java.sql.Statement;
  6. /**
  7. * account 表 修改记录
  8. */
  9. public class JDBC_Demo3 {
  10. public static void main(String[] args) {
  11. //修改王五的工资为1500
  12. Statement stmt=null;
  13. Connection conn=null;
  14. try {
  15. //1.注册驱动
  16. Class.forName("com.mysql.jdbc.Driver");
  17. //2.获取连接对象
  18. conn = DriverManager.getConnection("jdbc:mysql:///db3", "root", "root");
  19. //3.定义sql
  20. String sql="update account set balance=1500 where name='wangwu'";
  21. //4.获取执行sql的对象
  22. stmt = conn.createStatement();
  23. //5.执行sql
  24. int count = stmt.executeUpdate(sql);
  25. //6.处理结果
  26. System.out.println(count);
  27. if (count>0){
  28. System.out.println("修改成功");
  29. }else
  30. System.out.println("修改失败");
  31. } catch (ClassNotFoundException e) {
  32. e.printStackTrace();
  33. } catch (SQLException e) {
  34. e.printStackTrace();
  35. }finally {
  36. if (stmt!=null){
  37. try {
  38. stmt.close();
  39. } catch (SQLException e) {
  40. e.printStackTrace();
  41. }
  42. }
  43. if (conn!=null){
  44. try {
  45. conn.close();
  46. } catch (SQLException e) {
  47. e.printStackTrace();
  48. }
  49. }
  50. }
  51. }
  52. }
  • account表删除一条记录
  1. package cn.itcast.jdbc;
  2. import java.sql.Connection;
  3. import java.sql.DriverManager;
  4. import java.sql.SQLException;
  5. import java.sql.Statement;
  6. /**
  7. * 删除表中的记录
  8. */
  9. public class JDBCDemo4 {
  10. public static void main(String[] args) {
  11. //删除王五
  12. Statement stmt=null;
  13. Connection conn=null;
  14. try {
  15. //1.注册驱动
  16. Class.forName("com.mysql.jdbc.Driver");
  17. //2.获取连接对象
  18. conn = DriverManager.getConnection("jdbc:mysql:///db3", "root", "root");
  19. //3.定义sql
  20. String sql="delete from account where id=3";
  21. //4.获取执行sql的对象
  22. stmt = conn.createStatement();
  23. //5.执行sql
  24. int count = stmt.executeUpdate(sql);
  25. //6.处理结果
  26. System.out.println(count);
  27. if (count>0){
  28. System.out.println("删除成功");
  29. }else
  30. System.out.println("删除失败");
  31. } catch (ClassNotFoundException e) {
  32. e.printStackTrace();
  33. } catch (SQLException e) {
  34. e.printStackTrace();
  35. }finally {
  36. if (stmt!=null){
  37. try {
  38. stmt.close();
  39. } catch (SQLException e) {
  40. e.printStackTrace();
  41. }
  42. }
  43. if (conn!=null){
  44. try {
  45. conn.close();
  46. } catch (SQLException e) {
  47. e.printStackTrace();
  48. }
  49. }
  50. }
  51. }
  52. }
executeUpdate也可以执行DDL语句
  1. package cn.itcast.jdbc;
  2. import java.sql.Connection;
  3. import java.sql.DriverManager;
  4. import java.sql.SQLException;
  5. import java.sql.Statement;
  6. /**
  7. * 执行DDL语句
  8. */
  9. public class JDBCDemo5 {
  10. public static void main(String[] args) {
  11. //删除王五
  12. Statement stmt=null;
  13. Connection conn=null;
  14. try {
  15. //1.注册驱动
  16. Class.forName("com.mysql.jdbc.Driver");
  17. //2.获取连接对象
  18. conn = DriverManager.getConnection("jdbc:mysql:///db3", "root", "root");
  19. //3.定义sql
  20. String sql="create TABLE student(id INT, name VARCHAR(20))";
  21. //4.获取执行sql的对象
  22. stmt = conn.createStatement();
  23. //5.执行sql
  24. int count = stmt.executeUpdate(sql);
  25. //6.处理结果,DML返回结果,DDL不返回结果
  26. System.out.println(count);
  27. } catch (ClassNotFoundException e) {
  28. e.printStackTrace();
  29. } catch (SQLException e) {
  30. e.printStackTrace();
  31. }finally {
  32. if (stmt!=null){
  33. try {
  34. stmt.close();
  35. } catch (SQLException e) {
  36. e.printStackTrace();
  37. }
  38. }
  39. if (conn!=null){
  40. try {
  41. conn.close();
  42. } catch (SQLException e) {
  43. e.printStackTrace();
  44. }
  45. }
  46. }
  47. }
  48. }
DML会返回
DDL不会返回int值,只返回0
4.JDBC各个类详解_ResultSet
4.1 基本使用
Statement可以执行两类方法
  • int executeUpdate() 可以执行DML(insert update delete对表中数据进行修改)语句、DDL(对表和库进行修改,create、alter、drop,不常用,dba用SQL设置好)语句
  • (1)SQL数据操作语言(DML)语句的行计数或(2)0不返回的SQL语句 
    如update account set balance =1000;//返回影响的行数
    可以通过影响的行数判断DML是否执行成功,如果大于0,则执行成功,反之则失败
  • ResultSet executeQuery(String sql) :执行DQL(select)语句,返回ResultSet
    • ResultSet是一个结果集对象,用于封装查询结果
    • 目的:从resultset中将结果取出来
    • 方法:通过游标,取每一行,需要两类方法
    • next():游标向下移动一行
    • 获取每一列getXXX()获取数据
      • XXX代表数据类型
      • 如:int getInt(XX) getString(XX)
      • 参数中的值为获取的第几列,两种参数构成了重载
        • int:代表列的编号  如getString(1)   id,从1开始
        • Sting:代表列名,如getString("balance")
  1. package cn.itcast.jdbc;
  2. import java.sql.*;
  3. /**
  4. * 执行DDL语句
  5. */
  6. public class JDBCDemo6 {
  7. public static void main(String[] args) {
  8. //删除王五
  9. Statement stmt=null;
  10. Connection conn=null;
  11. ResultSet rs=null;
  12. try {
  13. //1.注册驱动
  14. Class.forName("com.mysql.jdbc.Driver");
  15. //2.获取连接对象
  16. conn = DriverManager.getConnection("jdbc:mysql:///db3", "root", "root");
  17. //3.定义sql
  18. String sql="select * from account";
  19. //4.获取执行sql的对象
  20. stmt = conn.createStatement();
  21. //5.执行sql
  22. rs = stmt.executeQuery(sql);//资源需要关闭
  23. //6.处理结果
  24. // 6.1游标向下移动一行
  25. rs.next();
  26. //6.2 获取数据
  27. int id = rs.getInt(1);
  28. String name = rs.getString("name");
  29. double balance = rs.getDouble(3);
  30. System.out.println(id+"---"+name+"---"+balance);
  31. } catch (ClassNotFoundException e) {
  32. e.printStackTrace();
  33. } catch (SQLException e) {
  34. e.printStackTrace();
  35. }finally {
  36. if (stmt!=null){
  37. try {
  38. stmt.close();
  39. } catch (SQLException e) {
  40. e.printStackTrace();
  41. }
  42. }
  43. if (conn!=null){
  44. try {
  45. conn.close();
  46. } catch (SQLException e) {
  47. e.printStackTrace();
  48. }
  49. }
  50. if (conn!=null){
  51. try {
  52. conn.close();
  53. } catch (SQLException e) {
  54. e.printStackTrace();
  55. }
  56. }
  57. if (rs!=null){
  58. try {
  59. rs.close();
  60. } catch (SQLException e) {
  61. e.printStackTrace();
  62. }
  63. }
  64. }
  65. }
  66. }
4.2 遍历结果集
注意:
  • 游标向下移动一行,判断当前行是否是最后一行末尾,如果是末尾,返回false,如果有数据返回true
    • boolean next() 将光标从当前位置向前移动一行。
  • 判断是否有数据
  • 获取数据
  1. package cn.itcast.jdbc;
  2. import java.sql.*;
  3. /**
  4. * 执行DDL语句
  5. */
  6. public class JDBCDemo7 {
  7. public static void main(String[] args) {
  8. //删除王五
  9. Statement stmt=null;
  10. Connection conn=null;
  11. ResultSet rs=null;
  12. try {
  13. //1.注册驱动
  14. Class.forName("com.mysql.jdbc.Driver");
  15. //2.获取连接对象
  16. conn = DriverManager.getConnection("jdbc:mysql:///db3", "root", "root");
  17. //3.定义sql
  18. String sql="select * from account";
  19. //4.获取执行sql的对象
  20. stmt = conn.createStatement();
  21. //5.执行sql
  22. rs = stmt.executeQuery(sql);//资源需要关闭
  23. //6.处理结果
  24. // 6.1游标向下移动一行
  25. while (rs.next()){
  26. //循环判断结果集是否有下一行
  27. //循环判断有标是否是最后一行末尾
  28. //6.2 获取数据
  29. int id = rs.getInt(1);
  30. String name = rs.getString("name");
  31. double balance = rs.getDouble(3);
  32. System.out.println(id+"---"+name+"---"+balance);
  33. }
  34. } catch (ClassNotFoundException e) {
  35. e.printStackTrace();
  36. } catch (SQLException e) {
  37. e.printStackTrace();
  38. }finally {
  39. if (stmt!=null){
  40. try {
  41. stmt.close();
  42. } catch (SQLException e) {
  43. e.printStackTrace();
  44. }
  45. }
  46. if (conn!=null){
  47. try {
  48. conn.close();
  49. } catch (SQLException e) {
  50. e.printStackTrace();
  51. }
  52. }
  53. if (conn!=null){
  54. try {
  55. conn.close();
  56. } catch (SQLException e) {
  57. e.printStackTrace();
  58. }
  59. }
  60. if (rs!=null){
  61. try {
  62. rs.close();
  63. } catch (SQLException e) {
  64. e.printStackTrace();
  65. }
  66. }
  67. }
  68. }
  69. }
4.3 JDBC练习_select语句
要求:查询emp表的数据,将其封装为对象,并打印
解决:通过集合,将对象装载到集合,并打印
    1. 定义Emp类
    2. 定义方法public List<Emp> findAll(){}
    3. 实现方法:select * from emp;
  1. package cn.itcast.domain;
  2. import java.util.Date;
  3. /**
  4. * 对应封装emp表数据的javabean
  5. */
  6. public class Emp {
  7. private int id;
  8. private String ename;
  9. private int job_id;
  10. private int mgr;
  11. private Date joindate;
  12. private double salary;
  13. private double bonus;
  14. private int dept_id;
  15. public int getId() {
  16. return id;
  17. }
  18. public void setId(int id) {
  19. this.id = id;
  20. }
  21. public String getEname() {
  22. return ename;
  23. }
  24. public void setEname(String ename) {
  25. this.ename = ename;
  26. }
  27. public int getJob_id() {
  28. return job_id;
  29. }
  30. public void setJob_id(int job_id) {
  31. this.job_id = job_id;
  32. }
  33. public int getMgr() {
  34. return mgr;
  35. }
  36. public void setMgr(int mgr) {
  37. this.mgr = mgr;
  38. }
  39. public Date getJoindate() {
  40. return joindate;
  41. }
  42. public void setJoindate(Date joindate) {
  43. this.joindate = joindate;
  44. }
  45. public double getSalary() {
  46. return salary;
  47. }
  48. public void setSalary(double salary) {
  49. this.salary = salary;
  50. }
  51. public double getBonus() {
  52. return bonus;
  53. }
  54. public void setBonus(double bonus) {
  55. this.bonus = bonus;
  56. }
  57. public int getDept_id() {
  58. return dept_id;
  59. }
  60. public void setDept_id(int dept_id) {
  61. this.dept_id = dept_id;
  62. }
  63. @Override
  64. public String toString() {
  65. return "Emp{" +
  66. "id=" + id +
  67. ", ename='" + ename + '\'' +
  68. ", job_id=" + job_id +
  69. ", mgr=" + mgr +
  70. ", joindate=" + joindate +
  71. ", salary=" + salary +
  72. ", bonuds=" + bonus +
  73. ", dept_id=" + dept_id +
  74. '}';
  75. }
  76. }
  1. package cn.itcast.jdbc;
  2. import cn.itcast.domain.Emp;
  3. import java.sql.*;
  4. import java.util.ArrayList;
  5. import java.util.List;
  6. /**
  7. * 定义一个方法,查询emp表的数据将其封装为对象,然后装载集合,并返回
  8. */
  9. public class JDBCDemo8 {
  10. public static void main(String[] args) {
  11. //想调用非静态方法,则需要创建对象
  12. List<Emp> list = new JDBCDemo8().findAll();
  13. System.out.println(list);
  14. }
  15. /**
  16. * 查询所有emp对象
  17. * @return
  18. */
  19. public List<Emp> findAll(){
  20. Connection conn=null;
  21. Statement stmt=null;
  22. ResultSet rs=null;
  23. List<Emp> list=null;
  24. try {
  25. //1.注册驱动
  26. Class.forName("com.mysql.jdbc.Driver");//最好写,写上可以向下兼容
  27. //2.获取连接
  28. conn = DriverManager.getConnection("jdbc:mysql:///db3", "root", "root");
  29. //3.定义sql
  30. String sql="select * from emp";
  31. //4.获取执行sql的对象
  32. stmt = conn.createStatement();
  33. //5.执行sql
  34. rs = stmt.executeQuery(sql);
  35. //6.遍历结果集,封装对象,装载集合
  36. Emp emp=null;
  37. list = new ArrayList<>();
  38. while(rs.next()){
  39. //获取数据
  40. int id = rs.getInt("id");
  41. String ename = rs.getString("ename");
  42. int job_id = rs.getInt("job_id");
  43. int mgr = rs.getInt("mgr");
  44. //怎么把光标放上就能显示概述?
  45. //Date是sql包下的类,继承了util的date,子类继承父类
  46. Date joindate = rs.getDate("joindate");
  47. double salary = rs.getDouble("salary");
  48. double bonus = rs.getDouble("bonus");
  49. int dept_id = rs.getInt("dept_id");
  50. //封装对象,对象引用复用
  51. emp=new Emp();
  52. emp.setId(id);
  53. emp.setBonus(bonus);
  54. emp.setDept_id(dept_id);
  55. emp.setEname(ename);
  56. emp.setJoindate(joindate);
  57. emp.setMgr(mgr);
  58. emp.setSalary(salary);
  59. list.add(emp);
  60. }
  61. } catch (ClassNotFoundException e) {
  62. e.printStackTrace();
  63. } catch (SQLException e) {
  64. e.printStackTrace();
  65. }finally {
  66. if (conn!=null){
  67. try {
  68. conn.close();
  69. } catch (SQLException e) {
  70. e.printStackTrace();
  71. }
  72. }
  73. if (stmt!=null){
  74. try {
  75. stmt.close();
  76. } catch (SQLException e) {
  77. e.printStackTrace();
  78. }
  79. }
  80. if (rs!=null){
  81. try {
  82. rs.close();
  83. } catch (SQLException e) {
  84. e.printStackTrace();
  85. }
  86. }
  87. }
  88. return list;
  89. }
  90. }
5.抽取JDBC工具类:JDBCUtils
分析:
上述代码重复度太高,每次都要注册驱动,每次都要获取连接对象
目标:
写工具类,简化代码,简化以后书写的操作
内容:
  • 注册驱动也抽取
  • 抽取一个方法,获取连接对象
    • 需求:不想传递参数(麻烦),还要保证工具类的通用性
    • 解决方案:通过配置文件解决此问题
      • jdbc.properties
        • url=
        • user=
        • password=
  • 抽取一个方法,释放资源
  1. package cn.itcast.utils;
  2. import java.io.FileReader;
  3. import java.io.IOException;
  4. import java.net.URL;
  5. import java.sql.*;
  6. import java.util.Properties;
  7. /**
  8. * JDBC工具类
  9. * 一个获取连接的方法
  10. * 一个释放资源的方法
  11. */
  12. public class JDBCUtils {
  13. private static String url;
  14. private static String user;
  15. private static String password;
  16. private static String driver;
  17. /**
  18. * 文件的读取,只需要读取一次就可以拿到这些值
  19. * 方案:通过静态代码块
  20. */
  21. static{
  22. //读取配置资源文件,获取值
  23. //BufeeredReader。。。麻烦
  24. try {
  25. //1.创建Properties集合类
  26. Properties prop=new Properties();
  27. //2.加载文件,代码提示
  28. //prop.load(new FileReader("src/jdbc.properties"));
  29. //找不到资源文件,最笨的方法---可以写绝对路径D:\IdeaProjects\liujinhui\day04_jdbc_20201220\src\jdbc.properties
  30. //另外:获取src路径下的文件--->ClassLoader 类加载器:可以 加载字节码文件进内存,同时可以获取src下的资源文件
  31. ClassLoader classLoader = JDBCUtils.class.getClassLoader();
  32. //传的是以src相对的文件路径
  33. //返回统一资源定位符,即文件的绝对路径
  34. URL res= classLoader.getResource("jdbc.properties");
  35. String path = res.getPath();
  36. System.out.println(path);
  37. prop.load(new FileReader(path));
  38. //3.获取数据,赋值
  39. url=prop.getProperty("url");
  40. user=prop.getProperty("user");
  41. password=prop.getProperty("password");
  42. driver=prop.getProperty("driver");
  43. //4.注册驱动
  44. Class.forName(driver);
  45. } catch (IOException e) {
  46. e.printStackTrace();
  47. } catch (ClassNotFoundException e) {
  48. e.printStackTrace();
  49. }
  50. }
  51. //Arrays等都是静态,方便类直接调用
  52. /**
  53. * 获取连接的工具方法
  54. * @return 连接对象
  55. */
  56. //String url,String root,String password有参数仍然很麻烦
  57. //通过私有变量、配置文件及静态代码块解决
  58. public static Connection getConnection() throws SQLException{
  59. return DriverManager.getConnection(url,user,password);
  60. }
  61. /**
  62. * 释放资源
  63. * @param stmt
  64. * @param conn
  65. */
  66. public static void close(Statement stmt,Connection conn){
  67. if (stmt!=null){
  68. try {
  69. stmt.close();
  70. //conn.close();多个语句要放到多个try..catch中
  71. } catch (SQLException e) {
  72. e.printStackTrace();
  73. }
  74. }
  75. if (conn!=null){
  76. try {
  77. conn.close();
  78. } catch (SQLException e) {
  79. e.printStackTrace();
  80. }
  81. }
  82. }
  83. /**
  84. * 释放资源
  85. * @param rs
  86. * @param stmt
  87. * @param conn
  88. */
  89. public static void close(ResultSet rs, Statement stmt, Connection conn){
  90. if (stmt!=null){
  91. try {
  92. stmt.close();
  93. //conn.close();多个语句要放到多个try..catch中
  94. } catch (SQLException e) {
  95. e.printStackTrace();
  96. }
  97. }
  98. if (conn!=null){
  99. try {
  100. conn.close();
  101. } catch (SQLException e) {
  102. e.printStackTrace();
  103. }
  104. }
  105. if (rs!=null){
  106. try {
  107. rs.close();
  108. } catch (SQLException e) {
  109. e.printStackTrace();
  110. }
  111. }
  112. }
  113. }
  1. package cn.itcast.jdbc;
  2. import cn.itcast.domain.Emp;
  3. import cn.itcast.utils.JDBCUtils;
  4. import java.sql.*;
  5. import java.util.ArrayList;
  6. import java.util.List;
  7. /**
  8. * 定义一个方法,查询emp表的数据将其封装为对象,然后装载集合,并返回
  9. */
  10. public class JDBCDemo8 {
  11. public static void main(String[] args) {
  12. //想调用非静态方法,则需要创建对象
  13. List<Emp> list = new JDBCDemo8().findAll2();
  14. System.out.println(list);
  15. }
  16. /**
  17. * 演示JDBC工具类
  18. * @return
  19. */
  20. public List<Emp> findAll2(){
  21. Connection conn=null;
  22. Statement stmt=null;
  23. ResultSet rs=null;
  24. List<Emp> list=null;
  25. try {
  26. //1.注册驱动
  27. //Class.forName("com.mysql.jdbc.Driver");//最好写,写上可以向下兼容
  28. //2.获取连接
  29. //conn = DriverManager.getConnection("jdbc:mysql:///db3", "root", "root");
  30. conn=JDBCUtils.getConnection();
  31. //3.定义sql
  32. String sql="select * from emp";
  33. //4.获取执行sql的对象
  34. stmt = conn.createStatement();
  35. //5.执行sql
  36. rs = stmt.executeQuery(sql);
  37. //6.遍历结果集,封装对象,装载集合
  38. Emp emp=null;
  39. list = new ArrayList<>();
  40. while(rs.next()){
  41. //获取数据
  42. int id = rs.getInt("id");
  43. String ename = rs.getString("ename");
  44. int job_id = rs.getInt("job_id");
  45. int mgr = rs.getInt("mgr");
  46. //怎么把光标放上就能显示概述?
  47. //Date是sql包下的类,继承了util的date,子类继承父类
  48. Date joindate = rs.getDate("joindate");
  49. double salary = rs.getDouble("salary");
  50. double bonus = rs.getDouble("bonus");
  51. int dept_id = rs.getInt("dept_id");
  52. //封装对象,对象引用复用
  53. emp=new Emp();
  54. emp.setId(id);
  55. emp.setBonus(bonus);
  56. emp.setDept_id(dept_id);
  57. emp.setEname(ename);
  58. emp.setJoindate(joindate);
  59. emp.setMgr(mgr);
  60. emp.setSalary(salary);
  61. list.add(emp);
  62. }
  63. }catch (SQLException e) {
  64. e.printStackTrace();
  65. }finally {
  66. JDBCUtils.close(rs,stmt,conn);
  67. }
  68. return list;
  69. }
  70. /**
  71. * 查询所有emp对象
  72. * @return
  73. */
  74. public List<Emp> findAll(){
  75. Connection conn=null;
  76. Statement stmt=null;
  77. ResultSet rs=null;
  78. List<Emp> list=null;
  79. try {
  80. //1.注册驱动
  81. Class.forName("com.mysql.jdbc.Driver");//最好写,写上可以向下兼容
  82. //2.获取连接
  83. conn = DriverManager.getConnection("jdbc:mysql:///db3", "root", "root");
  84. //3.定义sql
  85. String sql="select * from emp";
  86. //4.获取执行sql的对象
  87. stmt = conn.createStatement();
  88. //5.执行sql
  89. rs = stmt.executeQuery(sql);
  90. //6.遍历结果集,封装对象,装载集合
  91. Emp emp=null;
  92. list = new ArrayList<>();
  93. while(rs.next()){
  94. //获取数据
  95. int id = rs.getInt("id");
  96. String ename = rs.getString("ename");
  97. int job_id = rs.getInt("job_id");
  98. int mgr = rs.getInt("mgr");
  99. //怎么把光标放上就能显示概述?
  100. //Date是sql包下的类,继承了util的date,子类继承父类
  101. Date joindate = rs.getDate("joindate");
  102. double salary = rs.getDouble("salary");
  103. double bonus = rs.getDouble("bonus");
  104. int dept_id = rs.getInt("dept_id");
  105. //封装对象,对象引用复用
  106. emp=new Emp();
  107. emp.setId(id);
  108. emp.setBonus(bonus);
  109. emp.setDept_id(dept_id);
  110. emp.setEname(ename);
  111. emp.setJoindate(joindate);
  112. emp.setMgr(mgr);
  113. emp.setSalary(salary);
  114. list.add(emp);
  115. }
  116. } catch (ClassNotFoundException e) {
  117. e.printStackTrace();
  118. } catch (SQLException e) {
  119. e.printStackTrace();
  120. }finally {
  121. if (conn!=null){
  122. try {
  123. conn.close();
  124. } catch (SQLException e) {
  125. e.printStackTrace();
  126. }
  127. }
  128. if (stmt!=null){
  129. try {
  130. stmt.close();
  131. } catch (SQLException e) {
  132. e.printStackTrace();
  133. }
  134. }
  135. if (rs!=null){
  136. try {
  137. rs.close();
  138. } catch (SQLException e) {
  139. e.printStackTrace();
  140. }
  141. }
  142. }
  143. return list;
  144. }
  145. }
知识点:自定义工具类、配置文件、静态代码块
6.JDBC练习_登录案例
练习:
  • 通过键盘录入用户名和密码
  • 判断用户名是否登录成功select * from user where username="" and password="";
    • 如果此SQL有查询结果 ,则成功
步骤:
  • 创建一个数据库表user
  1. CREATE TABLE USER(
  2. id INT PRIMARY KEY AUTO_INCREMENT,
  3. username VARCHAR(32),
  4. PASSWORD VARCHAR(32)
  5. );
  6. SELECT * FROM USER;
  7. INSERT INTO USER VALUES(NULL,"zhangsan","123");
  8. INSERT INTO USER VALUES(NULL,"lisi","123");
  • 代码实现--创建登录方法
  1. package cn.itcast.jdbc;
  2. import cn.itcast.utils.JDBCUtils;
  3. import java.sql.Connection;
  4. import java.sql.ResultSet;
  5. import java.sql.SQLException;
  6. import java.sql.Statement;
  7. import java.util.Scanner;
  8. /**
  9. * 练习:
  10. 通过键盘录入用户名和密码
  11. 判断用户名是否登录成功
  12. */
  13. public class JDBCDemo9 {
  14. public static void main(String[] args) {
  15. //1.键盘录入,接收用户名和密码
  16. Scanner sc=new Scanner(System.in);
  17. System.out.println("请输入用户名:");
  18. String username = sc.nextLine();
  19. System.out.println("请输入密码:");
  20. String password = sc.nextLine();
  21. //2.调用方法
  22. //静态调用非静态需要声明对象
  23. boolean flag = new JDBCDemo9().login(username, password);
  24. //3.判断结果,输出不同语句
  25. if (flag){
  26. //登录成功
  27. System.out.println("登录成功");
  28. }else{
  29. System.out.println("用户名或密码错误");
  30. }
  31. //2.调用方法
  32. //3.判断结果,输出不同语句
  33. }
  34. /**
  35. * 登录方法
  36. */
  37. public boolean login(String username ,String password){
  38. if (username==null||password==null){
  39. return false;
  40. }
  41. Connection conn=null;
  42. Statement stmt=null;
  43. ResultSet rs=null;
  44. try {
  45. //连接数据库判断是否登录成功
  46. //1.获取连接,更改数据库只需要修改配置文件,可扩展性强
  47. conn = JDBCUtils.getConnection();
  48. //2.定义 sql
  49. String sql="select * from user where username='"+username+"' and password='"+password+"'";
  50. //3.获取执行SQL的对象
  51. stmt = conn.createStatement();
  52. //4.执行查询
  53. rs = stmt.executeQuery(sql);
  54. //5.判断
  55. /*if (rs.next()){
  56. return true;
  57. }else{
  58. return false;
  59. }*/
  60. //直接返回
  61. return rs.next();
  62. } catch (SQLException e) {
  63. e.printStackTrace();
  64. }finally {
  65. JDBCUtils.close(rs,stmt,conn);
  66. }
  67. return false;
  68. }
  69. }
7.JDBC各个类详解_PreparedStatement
上述方法存在的问题 :
  • SQL注入问题:在拼接sql时,有一些sql的特殊关键字参与字符串的拼接,会造成安全性问题
    • 输入密码时输入:a' or 'a' = 'a ,可以登录成功
    • 输出的SQL语句:select * from user where username='dsgdf' and password='a' or 'a' = 'a'
    • 在 sqlyog中可以 查到所有记录
  • 解决sql注入问题:使用PreparedStatement对象来解决
    • 是statement的子接口,是 一个预编译的接口
    • 预编译的sql:参数使用?作为占位符
  • 使用步骤
    • 导入驱动jar包
    • 注册驱动
    • 获取数据库的连接对象Connection(java和数据库的桥梁对象)
    • 定义SQL语句
      • 注意:SQL的参数使用?作为占位符
      • 如:select * from user where username=?  and password=?
    • 获取执行SQL语句的对象PreparedStatement   PreparedStatement prepareStatement(String sql)
    • 给?赋值
      • 方法:setXXX(参数1,参数 2)
      • 参数 1:?的位置,从1开始
      • 参数2:?的值
    • 执行SQL,接收返回的结果,不需要传递 SQL语句ResultSet executeQuery()
    • 处理结果
    • 释放资源,不释放容易造成内存的泄露问题
  • 注意:后期都会使用PreparedStatement对象来完成增删改查 操作
    • 可以防止SQL注入
    • 效率更高
  1. package cn.itcast.jdbc;
  2. import cn.itcast.utils.JDBCUtils;
  3. import java.sql.*;
  4. import java.util.Scanner;
  5. /**
  6. * 使用PrepareStatement实现登录操作
  7. * 练习:
  8. 通过键盘录入用户名和密码
  9. 判断用户名是否登录成功
  10. */
  11. public class JDBCDemo10 {
  12. public static void main(String[] args) {
  13. //1.键盘录入,接收用户名和密码
  14. Scanner sc=new Scanner(System.in);
  15. System.out.println("请输入用户名:");
  16. String username = sc.nextLine();
  17. System.out.println("请输入密码:");
  18. String password = sc.nextLine();
  19. //2.调用方法
  20. //静态调用非静态需要声明对象
  21. boolean flag = new JDBCDemo10().login(username, password);
  22. //3.判断结果,输出不同语句
  23. if (flag){
  24. //登录成功
  25. System.out.println("登录成功");
  26. }else{
  27. System.out.println("用户名或密码错误");
  28. }
  29. //2.调用方法
  30. //3.判断结果,输出不同语句
  31. }
  32. /**
  33. * 登录方法
  34. */
  35. public boolean login(String username ,String password){
  36. if (username==null||password==null){
  37. return false;
  38. }
  39. Connection conn=null;
  40. PreparedStatement pstmt=null;
  41. ResultSet rs=null;
  42. try {
  43. //连接数据库判断是否登录成功
  44. //1.获取连接,更改数据库只需要修改配置文件,可扩展性强
  45. conn = JDBCUtils.getConnection();
  46. //2.定义 sql
  47. String sql="select * from user where username= ? and password= ?";
  48. //System.out.println(sql);
  49. //3.获取执行SQL的对象
  50. pstmt = conn.prepareStatement(sql);
  51. //给 ?赋值
  52. pstmt.setString(1,username);
  53. pstmt.setString(2,password);
  54. //4.执行查询
  55. rs =pstmt.executeQuery();
  56. //5.判断
  57. /*if (rs.next()){
  58. return true;
  59. }else{
  60. return false;
  61. }*/
  62. //直接返回
  63. return rs.next();
  64. } catch (SQLException e) {
  65. e.printStackTrace();
  66. }finally {
  67. JDBCUtils.close(rs,pstmt,conn);
  68. }
  69. return false;
  70. }
  71. }
三、使用JDBC控制事务
1.事务:包含多个步骤的业务操作,如果这个业务操作被事务管理,则这多个事务要么同时成功,要么同时失败
2.操作
  • 开启事务
  • 提交事务
  • 回滚事务
3.回顾:Connection对象可以进行获取连接和管理事务
使用Connection对象管理事务
  • 三个方法--开启事务void setAutoCommit(boolean autoCommit) 调用此方法设置false,即开启事务并不自动提交
  • 三个方法--提交事务:void commit() 提交事务
  • 三个方法--回滚事务:void rollback() 回滚事务
4.银行转账案例--JDBC控制事务 
  1. package cn.itcast.jdbc;
  2. import cn.itcast.utils.JDBCUtils;
  3. import java.sql.Connection;
  4. import java.sql.PreparedStatement;
  5. import java.sql.SQLException;
  6. /**
  7. * 事务操作
  8. */
  9. public class JDBCDemo11 {
  10. public static void main(String[] args) {
  11. Connection conn=null;
  12. PreparedStatement pstmt1=null;
  13. PreparedStatement pstmt2=null;
  14. try {
  15. //1.获取连接
  16. conn = JDBCUtils.getConnection();
  17. //开启事务
  18. conn.setAutoCommit(false);
  19. //2,定义SQL
  20. //2.1 张三-500
  21. //String sql1="update account set balance=balance-500 where id=1";
  22. //2.2 李四+500
  23. //String sql2="update account set balance=balance+500 where id=2";
  24. //通用写法
  25. String sql1="update account set balance=balance-? where id=?";
  26. String sql2="update account set balance=balance+? where id=?";
  27. //3.获取执行sql对象
  28. pstmt1 = conn.prepareStatement(sql1);
  29. pstmt2= conn.prepareStatement(sql2);
  30. //代码格式化快捷键
  31. //4.设置参数
  32. pstmt1.setDouble(1,500);
  33. pstmt1.setInt(2,1);
  34. pstmt2.setDouble(1,500);
  35. pstmt2.setInt(2,2);
  36. //5.执行SQL
  37. pstmt1.executeUpdate();
  38. //手动制造异常
  39. int i=3/0;
  40. pstmt2.executeUpdate();
  41. //提交事务
  42. conn.commit();
  43. //使用大异常
  44. } catch (Exception e) {
  45. try {
  46. //事务回滚,前提不为null
  47. if (conn!=null){
  48. conn.rollback();
  49. }
  50. } catch (SQLException e1) {
  51. e1.printStackTrace();
  52. }
  53. e.printStackTrace();
  54. }finally {
  55. JDBCUtils.close(pstmt1,conn);
  56. JDBCUtils.close(pstmt2,null);
  57. }
  58. }
  59. }
在执行sql之前开启事务
在当所有sql执行完提交事务
在 catch中回滚事务

JavaEE Day05 JDBC(用Java语言操作数据库)的更多相关文章

  1. Java数据库连接——JDBC基础知识(操作数据库:增删改查)

    一.JDBC简介 JDBC是连接java应用程序和数据库之间的桥梁. 什么是JDBC? Java语言访问数据库的一种规范,是一套API. JDBC (Java Database Connectivit ...

  2. Java程序操作数据库SQLserver详解

    数据库基本操作:增删改查(CRUD) crud介绍(增.删.改.查操作) CRUD是指在做计算处理时的增加(Create).查询(Retrieve)(重新得到数据).更新(Update)和删除(Del ...

  3. 39.C语言操作数据库

    一.准备工作: sqlite3工具集:链接:https://pan.baidu.com/s/1mjufXZa 密码:2ui7 安装步骤: 打开如下文件夹,找到sqlite3.dll,并放入系统目录 2 ...

  4. 借助Java的JDBC自制“DBMS”管理操作数据库

    package jdbc; import java.sql.Connection; import java.sql.Driver; import java.sql.DriverManager; imp ...

  5. JDBC(用Eclipse操作数据库Oracle)的基础操作集合

    JDBC: JDBC(Java Data Base Connectivity,java数据库连接)是一种用于执行SQL语句的Java API,可以为多种关系数据库提供统一访问,它由一组用Java语言编 ...

  6. R语言操作数据库

    以下内容出自http://www.douban.com/note/172387172/ CRAN上有很多R的数据库支持包,使R能够对数据库进行读写操作.这些包有:RODBC.DBI.RMySQL.RO ...

  7. (1)JDBC基础-java链接mysql数据库

    怎么操作数据库: 1,通过客户端(比如mac的终端,或者sql pro等专业工具)登陆数据库服务器(mysql -u root -p) 2,编写sql语句 3,发生sql语句到数据库服务器执行. JD ...

  8. IDEA用Maven连接MySQL的jdbc驱动,并操作数据库

    1.在IDEA里创建Maven项目 1.1.点击Create New Project   1.2.选择Maven,JDK这里用的是1.8,点击Next  1.3.填入“组织名”.“项目名”,版本是默认 ...

  9. IDEA导入MySQL的jdbc驱动,并操作数据库

    将MySQL的jdbc驱动,导入IDEA的方式,虽然也能连接并且操作数据库,但并不推荐这种方式,推荐使用Maven工程的方式:https://www.cnblogs.com/dadian/p/1193 ...

  10. 【JDBC】Java程序的数据库初体验

    JDBC是什么 JDBC是一种能够用来执行SQL语句的Java API[接口]. 它是Java提供的一种规范,让各大数据库厂商遵循此规范完成自己的数据库连接驱动[实现接口]. JDBC的入门程序(这里 ...

随机推荐

  1. 前端实现docx、pdf格式文件在线预览

    theme: vuepress highlight: atelier-heath-light 介绍 在业务中,如果遇到文档管理类的功能,会出现需要在线预览的业务需求,本文主要是通过第三方库来实现文档预 ...

  2. 关于使用kuboard安装其自带的监控应用授权普通用户使用

    官方文档地址:https://www.kuboard.cn/guide/example/monitor-v2.html#授权用户访问套件

  3. CentOS6 配置阿里云 NTP 服务

    本文以Centos 6.5为例介绍如何修改Linux实例时区,以及开启和配置Linux NTP服务,保证实例本地时间精确同步. 前提条件 NTP服务的通信端口为UDP 123,设置NTP服务之前请确保 ...

  4. 关闭You have new mail in /var/spool/mail/root提醒

    echo "unset MAILCHECK">> /etc/profile #以root权限执行 或者用sudo source /etc/profile cat /de ...

  5. PHP全栈开发(八):CSS Ⅲ background

    设置背景颜色: div { background-color:#b0c4de; } 不仅可以给body标签设置背景颜色,还能给p,div,h标签设置背景颜色 设置背景图片: body { backgr ...

  6. 从源码分析 MGR 的新主选举算法

    MGR 的新主选举算法,在节点版本一致的情况下,其实也挺简单的. 首先比较权重,权重越高,选为新主的优先级越高. 如果权重一致,则会进一步比较节点的 server_uuid.server_uuid 越 ...

  7. 关于javascript:void(0) 在不用的浏览器当中的表现

    原因在于三款浏览器,对三个属性的处理顺序不同. Chrome顺序:onclick -> href -> target IE和Firefox顺序:onclick -> target - ...

  8. Windows活动目录_票据——敬请期待!

    票据:域控&域机子之间的信任密钥 [缺省40天更换一次] 域用户登录过程 域用户的账户密码(用信任密钥加密的)传递至域控: 域控验证账户密码成功后,构造域用户SID和组SID(用信任密钥加密的 ...

  9. Redis5种数据类型

    字符串 @GetMapping("/string") public String stringTest(){ redisTemplate.opsForValue().set(&qu ...

  10. 一天十道Java面试题----第四天(线程池复用的原理------>spring事务的实现方式原理以及隔离级别)

    这里是参考B站上的大佬做的面试题笔记.大家也可以去看视频讲解!!! 文章目录 31.线程池复用的原理 32.spring是什么? 33.对Aop的理解 34.对IOC的理解 35.BeanFactor ...