永远学不会的Java|JDBC炼气篇-1


JDBC炼气篇-1

    • 介绍
      • 简介
      • 主要步骤
    • 详解各个对象
      • DriverManager
      • Connection
      • Statement
      • ResultSet
      • PreparedStatement
    • 代码实现
      • 增加一条记录(insert)
      • 修改一条记录(update)
      • 删除一条记录(delete)
      • 执行DDL语句(了解)
      • 执行查询
      • JDBC工具类
      • 配置文件
      • 将表中数据 封装对象 装载集合 返回
    • 打怪篇

介绍 这篇博客是一只菜汪学习JDBC的第一步。
这篇博客更多地是Statement和不用JDBCUtils的写法。
欲知后事如何请看下集:(/▽\)
简介
JDBC本质:官方定义的一套操作所有关系型数据库的规则,即 接口 。各个数据库厂商去实现这套接口,提供数据库驱动jar包。我们可以使用这套接口(JDBC)编程,真正执行的代码是驱动jar包中的 实现类
主要步骤
  1. 导入驱动jar包 例如:mysql-connector-java-5.1.37-bin.jar
  2. 注册驱动
  3. 获取数据库连接对象 Connection
  4. 获取执行sql语句的对象 Statement
  5. 定义sql
  6. 执行sql,接受返回结果
  7. 处理结果
  8. 释放资源
详解各个对象
类名 作用
DriverManager 驱动管理对象
Connection 数据库连接对象
Statement 执行sql的对象
ResultSet 结果集对象,封装查询结果
PreparedStatement 执行sql的对象
DriverManager
功能:
  1. 注册驱动,告诉程序该使用哪一个数据库驱动jar包
    通过查看源码发现:在com.mysql.jdbc.Driver类中存在静态代码块 static { try { java.sql.DriverManager.registerDriver(new Driver()); } catch (SQLException E) { throw new RuntimeException("Can't register driver!"); } }

    注意: mysql5 之后的驱动jar包可以省略注册驱动的步骤。
  2. 获取数据库连接
    方法:static Connection getConnection(String url, String user, String password) 参数: * url:指定连接的路径 * 语法:jdbc:mysql://ip地址(域名):端口号/数据库名称 * 例子:jdbc:mysql://localhost:3306/db3 * 细节:如果连接的是本机mysql服务器,并且mysql服务默认端口是3306,则url可以简写为:jdbc:mysql:///数据库名称 * user:用户名 * password:密码

Connection
功能:
  1. 获取执行sql的对象
    • Statement createStatement()
    • PreparedStatement prepareStatement(String sql)
  2. 管理事务:
    • 开启事务:setAutoCommit(boolean autoCommit):调用该方法设置参数为false,即开启事务。
    • 提交事务:commit()
    • 回滚事务:rollback()
Statement
功能:
  1. 执行sql
    • 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)语句
ResultSet
方法:
  • boolean next(): 游标向下移动一行,判断当前行是否是最后一行末尾(是否有数据),如果是,则返回false,如果不是则返回true
  • getXxx(参数):获取数据
    ? Xxx:代表数据类型,如: int getInt() , String getString()
    ? 参数:
    ? 1. int : 代表列的编号,从1开始。如: getString(1)
    ? 2. String:代表列名称。 如: getDouble(“balance”)
使用步骤:
  1. 游标向下移动一行
  2. 判断是否有数据
  3. 获取数据
代码:
while(rs.next()){ //获取数据 int id = rs.getInt(1); String name = rs.getString("name"); double balance = rs.getDouble(3); System.out.println(id + "---" + name + "---" + balance); }

PreparedStatement
功能:
  1. 解决 sql 注入问题:在拼接sql时,有一些sql的特殊关键字参与字符串的拼接。会造成安全性问题
    • 输入用户随便,输入密码:a' or 'a' = 'a
    • sql:select * from user where username = 'fhdsjkf' and password = 'a' or 'a' = 'a'
  2. 解决sql注入问题:使用PreparedStatement对象来解决
  3. 预编译的SQL:参数使用 ? 作为占位符
  4. 注意:后期都会使用PreparedStatement来完成增删改查的所有操作
    • 可以防止SQL注入
    • 效率更高
    • 但是在需要拼接字符串形成sql语句的时候,需要用到Statement语句
代码实现 大型白学现场注意:
  • 此处使用的是Statement类实现,但是在实际中很少用到Statement(),用到更多的是PreparedStatement()
  • 此处未使用JDBCUtil工具类,所以代码冗杂
  • 更多精彩请见下篇博客【JDBC筑基篇-1】
增加一条记录(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.获取Connection对象 conn = DriverManager.getConnection("jdbc:mysql:///db3", "root", "root"); //3.获取执行sql的对象 Statement stmt = conn.createStatement(); //4. 定义sql String sql = "insert into account values(null,'王五',3000)"; //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(); } } } } }

修改一条记录(update)
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:///db3", "root", "root"); //3.获取执行sql对象 stmt = conn.createStatement(); //4.定义sql String sql= "update account set balance = 1500 where id = 3"; //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(); } } } } }

删除一条记录(delete)
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:///db3", "root", "root"); //3.获取执行sql对象 stmt = conn.createStatement(); //4.定义sql String sql= "delete from account where id = 3"; //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(); } } } } }

执行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:///db3", "root", "root"); //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(); } } } } }

执行查询
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:///db3", "root", "root"); //3.定义sql String sql= "select * from account"; //4.获取执行sql对象 stmt = conn.createStatement(); //5.执行sql rs = stmt.executeQuery(sql); //6.处理结果 //循环判断游标是否是最后一行末尾 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(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(); } } } } }

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 res= classLoader.getResource("jdbc.properties"); String path = res.getPath(); //2. 加载文件 // pro.load(new FileReader("D:\\IdeaProjects\\itcast\\day04_jdbc\\src\\jdbc.properties")); 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(); } }// 获取连接 public static Connection getConnection() throws SQLException { return DriverManager.getConnection(url, user, password); }// 释放资源 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(); } } }// 释放资源 —— 重载 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(); } } } }

配置文件
url=jdbc:mysql:///db3 user=root password=root driver=com.mysql.jdbc.Driver

注:配置文件中不要书写空格
将表中数据 封装对象 装载集合 返回
public class JDBCDemo8 { // 测试方法 public static void main(String[] args) { List list = new JDBCDemo8().findAll2(); System.out.println(list); System.out.println(list.size()); } // 查询所有emp对象的方法 public List findAll(){ Connection conn = null; Statement stmt = null; ResultSet rs = null; List list = null; try { //1.注册驱动 Class.forName("com.mysql.jdbc.Driver"); //2.获取连接 conn = DriverManager.getConnection("jdbc:mysql:///db3", "root", "root"); //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(); 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; }//演示JDBC工具类 public List findAll2(){ Connection conn = null; Statement stmt = null; ResultSet rs = null; List list = null; try { 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(); 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 (SQLException e) { e.printStackTrace(); }finally { JDBCUtils.close(rs,stmt,conn); } return list; } }

打怪篇 已定义如下代码,自己看着办完成增删改查。(定义Course对象)
import java.util.List; // 课程要求:Dao接口 public interface ICourseDao { public int insert(Course course) throws Exception; public int delete(int id) throws Exception; public int update(Course course) throws Exception; public List select() throws Exception; }

解答:
import java.sql.*; // 定义JDBC工具类 public class JDU { public static Connection getConnection() { Connection conn = null; String url = "jdbc:mysql://localhost:3306/java09"; String name = "root"; String password = "333"; try { // 注册驱动 Class.forName("com.mysql.cj.jdbc.Driver"); // 获取连接 conn = DriverManager.getConnection(url, name, password); } catch (SQLException | ClassNotFoundException e) { e.printStackTrace(); } return conn; }// 关闭数据库资源 public static void close(PreparedStatement pst, Connection conn) throws Exception { if (pst != null) { pst.close(); } if (conn != null) { conn.close(); } }// 关闭数据库资源 —— 方法重载 public static void close(ResultSet rs, PreparedStatement pst, Connection conn) throws Exception { if (rs != null) { rs.close(); } if (pst != null) { pst.close(); } if (conn != null) { conn.close(); } } }

// 定义Course课程类 public class Course { private int id; private String name; private int credit; // 构造方法 public Course() { }public Course(String name, int credit) { this.name = name; this.credit = credit; }// 为属性提供访问接口 public int getId() { return id; }public void setId(int id) { this.id = id; }public String getName() { return name; }public void setName(String name) { this.name = name; }public double getCredit() { return credit; }public void setCredit(int credit) { this.credit = credit; } }

// 接口Dao的实现类 【!!!】 import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.util.ArrayList; import java.util.List; class ICourseDaoImpl implements ICourseDao { // 定义sql语句 private static final String SQL_INSERT = "insert into course (name,credit) values(?,?)"; private static final String SQL_DELETE = "delete from course where id=?"; private static final String SQL_UPDATE = "update course set name=?,credit=? where id=?"; public int insert(Course course) throws Exception { return update(SQL_INSERT, new Object[]{course.getName(), course.getCredit(),}); }public int delete(int i) throws Exception { return update(SQL_DELETE, new Object[]{i}); }public int update(Course course) throws Exception { int flag = update(SQL_UPDATE, new Object[]{course.getName(), course.getCredit(), course.getId()}); return flag; } //定义update方法,传入对数据库进行修改的操作 public int update (String sql, Object[]param) throws Exception { int flag = 0; Connection conn = null; PreparedStatement pst = null; try { conn = JDU.getConnection(); pst = conn.prepareStatement(sql); if (param != null && param.length > 0) { for (int i = 1; i < param.length + 1; i++) { pst.setObject(i, param[i - 1]); } } flag = pst.executeUpdate(); } finally { JDU.close(pst, conn); } return flag; }//定义select方法,进行数据库查询的操作,将查询的结果放在对象Course的集合List中 public List select() throws Exception { List cl = null; Connection conn = null; PreparedStatement pstm = null; ResultSet rs = null; try { conn = JDU.getConnection(); pstm = conn.prepareStatement("select * from course"); rs = pstm.executeQuery(); cl = new ArrayList(); while (rs.next()) { Course c = new Course(); c.setId(rs.getInt("id")); c.setName(rs.getString("name")); c.setCredit(rs.getInt("credit")); cl.add(c); } return cl; } finally { JDU.close(rs, pstm, conn); } } }

// 测试类 import java.sql.SQLException; import java.util.List; // 编写测试程序 public class Test { public static void main(String[] args) { ICourseDaoImpl dao=new ICourseDaoImpl(); // 接口的实现类 Course c=null; List l = null; // 准备集合 存放Course对象try { // 插入 c = new Course("最讨厌的高数", 2); // 插入学科名字为“最讨厌的高数” 学分为2分 dao.insert(c); // 将课程插入数据库 // 查询 l = dao.select(); System.out.println("数据库中的信息如下:"); for (Course i : l) { // 循环,打印所有课程的信息 System.out.println("【"+i.getId() + "】---" + i.getName() +"---" + i.getCredit()); if(i.getName().equals("最讨厌的高数")) c.setId(i.getId()); } // 修改 c.setName("辣鸡高数"); dao.update(c); // 执行更新操作 System.out.println(c.getId()); dao.delete(57); // 删除第57号学科信息 l = dao.select(); System.out.println("修改过后的学科信息:"); for (Course i : l) { // 循环遍历 打出所有学科信息 System.out.println("【"+i.getId() + "】---" + i.getName() + "---" + i.getCredit()); } } catch (SQLException e1) { e1.printStackTrace(); } catch (Exception e) { e.printStackTrace(); }} }

【永远学不会的Java|JDBC炼气篇-1】数据库定义:永远学不会的Java|JDBC炼气篇-1
文章图片

(这是一个程序中间出错测试了65遍程序终于成功的菜汪……这个id是自动递增的你敢信T^T)

    推荐阅读