数据库开发基础(Java)

时间:2024-05-17日,星期五

文章内容

JDBC快速入门、使用JDBC开发细节、连接池与JDBC进阶使用

  • JDBC使用步骤

  • 数据库查询方法

  • 数据库写入方法

  • SQL注入攻击的应对

  • 连接池的使用

  • Apache Commons DBUtils

JDBC快速入门

JDBC是Java中为了去方便使用各种数据库而创造出来的,在java开发过程中可以使用JDBC API进而对不同的数据库进行驱动使用。

JDBC的优点

  • 统一的API,提供一致的开发过程

  • 易于学习,容易上手,代码结构稳定

  • 功能强大,执行效率高,可处理海量数据

JDBC开发流程
  1. 加载并注册JDBC驱动

  2. 创建数据库连接

  3. 创建Statement对象

  4. 遍历查询结果

  5. 关闭连接,释放资源

    public static void main(String[] args){
         Connection conn=null;
         try {
             //1. 加载并注册JDBC驱动
             Class.forName("com.mysql.cj.jdbc.Driver");
             //2. 创建数据库连接
             conn = DriverManager.getConnection(
                     "jdbc:mysql://localhost:3306/learning_jdbc?serverTimezone=UTC","root","123456"
             );
             //3. 创建Statement对象
             Statement stmt = conn.createStatement();
             ResultSet rs = stmt.executeQuery("SELECT * FROM employee");
             //4. 遍历查询结果
             while(rs.next()){
                 Integer eno= rs.getInt(1);
                 String name = rs.getString("ename");
                 Float salary = rs.getFloat("salary");
                 String dname = rs.getString("dname");
                 Date hiredate = rs.getDate("hiredate");
                 System.out.println(eno+"-"+name+"-"+salary+"-"+dname+"-"+ hiredate);
             }
         }catch (Exception e){
             e.printStackTrace();
         }finally {
             try {
                 //5. 关闭连接,释放资源
                 if (conn != null && conn.isClosed() == false){
                     conn.close();
                 }
             } catch (SQLException throwables) {
                 throwables.printStackTrace();
             }
         }
     }

JDBC开发流程细节

各数据库与连接字符串:

JDBC连接的对象Connection,通过TCP/IP协议,连通JDBC应用(Java程序)与MySQL数据库服务器的3306端口

  //2. 创建数据库连接
             conn = DriverManager.getConnection(
                     "jdbc:mysql://localhost:3306/learning_jdbc?serverTimezone=UTC","root","123456"
             )

其中的参数包括了连接字符串与数据库用户名和密码

MySQL连接字符串:

  • 格式:jdbc:mysql://主机ip:端口/数据库名?参数列表

  • 主机ip与端口是可选设置,默认值为127.0.0.1与3306

  • 参数列表采用url编码,格式:参数1=值1&参数2=值2&..

SQL注入攻击问题

  • SQL注入攻击是指利用SQL漏洞越权获取数据的黑客行为

  • SQL注入攻击根源是对原始SQL中的敏感字符做特殊处理

  • 解决方法:放弃Statement改用PrepareStatement处理SQL

    • Statement方法对符号单引号没有进行处理,会被SQL注入,使用PreStatement能防范SQL注入。

PrepareStatement

  • PrepareStatement预编译Statement是Statement的子接口

  • PrepareStatement对SQL进行参数化,预防SQL注入攻击

  • PreparedStatement比Statement执行效率更高

  •  String pdname = in.nextLine();
             String pdname = "市场部";//输入参数
             Connection conn=null;
             try {
                 //1. 加载并注册JDBC驱动
                 Class.forName("com.mysql.cj.jdbc.Driver");
                 //2. 创建数据库连接
                 conn = DriverManager.getConnection(
                         "jdbc:mysql://localhost:3306/learning_jdbc?serverTimezone=UTC","root","123456"
                 );
                 //3. 创建Statement对象
                 String sql = "SELECT * FROM employee WHERE dname=?";
                 PreparedStatement pStmt = conn.prepareStatement(sql);
                 pStmt.setString(1,pdname);
                 ResultSet rs = pStmt.executeQuery("SELECT * FROM employee WHERE dname='"+ pdname+"'");
                 //4. 遍历查询结果
                 while(rs.next()){
                     Integer eno= rs.getInt(1);
                     String name = rs.getString("ename");
                     Float salary = rs.getFloat("salary");
                     String dname = rs.getString("dname");
                     Date hiredate = rs.getDate("hiredate");
                     System.out.println(eno+"-"+name+"-"+salary+"-"+dname+"-"+ hiredate);
                 }
             }catch (Exception e){
                 e.printStackTrace();
             }finally {
                 try {
                     //5. 关闭连接,释放资源
                     if (conn != null && conn.isClosed() == false){
                         conn.close();
                     }
                 } catch (SQLException throwables) {
                     throwables.printStackTrace();
                 }
             }

时间:2024-05-19日,星期天

JDBC进行数据库操作

将上面的数据库连接和数据库连接资源关闭方法进行封装,得到DBUtils,数据库工具文件

 package com.imooc.jdbc.common;
 ​
 import java.sql.*;
 ​
 public class DBUtils {
     /**
      * 获取数据库连接
      * @return返回数据库连接
      * @throws ClassNotFoundException
      * @throws SQLException
      */
     public static Connection getConnection() throws ClassNotFoundException, SQLException {
         //1. 加载并注册JDBC驱动
         Class.forName("com.mysql.cj.jdbc.Driver");
         //2. 创建数据库连接
         Connection conn = DriverManager.getConnection(
                 "jdbc:mysql://localhost:3306/learning_jdbc?serverTimezone=UTC","root","123456"
         );
         return conn;
     }
 ​
     /**
      * 关闭数据库连接相关资源
      * @param rs 数据库返回结果集
      * @param stmt 数据库预处理查询语句
      * @param conn 数据库连接
      */
     public static void closeConnection(ResultSet rs, Statement stmt, Connection conn){
         if (rs !=null){
             try {
                 //关闭结果连接,释放资源
                 rs.close();
             } catch (SQLException throwables) {
                 throwables.printStackTrace();
             }
         }
         if (stmt != null){
             try {
                 //关闭连接,释放资源
                 stmt.close();
             } catch (SQLException throwables) {
                 throwables.printStackTrace();
             }
         }
         try {
             //5. 关闭连接,释放资源
             if (conn != null && conn.isClosed() == false){
                 conn.close();
             }
         } catch (SQLException throwables) {
             throwables.printStackTrace();
         }
     }
 }

JDBC执行插入操作
 public class InsertCommand implements Command{
     @Override
     public void execute() {
         Scanner in = new Scanner(System.in);
         System.out.println("请输入员工编号:");
         int eno = in.nextInt();
         System.out.println("请输入员工姓名:");
         String ename = in.next();
         System.out.println("请输入员工薪资:");
         float salary = in.nextFloat();
         System.out.println("请输入隶属部门");
         String dname = in.next();
         Connection conn = null;
         PreparedStatement pStmt = null;
         try {
             conn = DBUtils.getConnection();
             String sql = "INSERT INTO employee(eno,ename,salary,dname) VALUES(?,?,?,?)";//插入语句
             pStmt = conn.prepareStatement(sql);
             pStmt.setInt(1,eno);
             pStmt.setString(2,ename);
             pStmt.setFloat(3,salary);
             pStmt.setString(4,dname);
             int cnt = pStmt.executeUpdate();//执行更新方法,返回插入的条数
             System.out.println("数据新增成功条数:"+cnt);
             System.out.println(ename+"已成功办理入职");
         } catch (ClassNotFoundException e) {
             e.printStackTrace();
         } catch (SQLException throwables) {
             throwables.printStackTrace();
         }finally {
             DBUtils.closeConnection(null,pStmt,conn);
         }
     }
 }
 ​
JDBC执行更新和删除操作

//更新

 /调整员工薪资
 public class UpdateCommand implements Command {
     @Override
     public void execute() {
         Scanner in = new Scanner(System.in);
         System.out.println("请输入要调整的员工编号");
         int eno = in.nextInt();
         System.out.println("请输入要调整到的薪资");
         float salary = in.nextFloat();
         Connection conn = null;
         PreparedStatement pStmt = null;
 ​
         try {
             conn = DBUtils.getConnection();
             String sql = "UPDATE employee SET salary=? WHERE eno=?";
             pStmt = conn.prepareStatement(sql);
             pStmt.setFloat(1,salary);
             pStmt.setInt(2, eno);
             int cnt = pStmt.executeUpdate();
             if (cnt == 1){
                 System.out.println("员工编号"+eno+"薪资已调整到"+salary);
             }else{
                 System.out.println("未找到员工编号为:"+eno+"的员工");
             }
         } catch (ClassNotFoundException e) {
             e.printStackTrace();
         } catch (SQLException throwables) {
             throwables.printStackTrace();
         }finally {
             DBUtils.closeConnection(null,pStmt,conn);
         }
     }
 }

//删除

 ​
 public class DeleteCommand implements Command{
     @Override
     public void execute() {
         Scanner in = new Scanner(System.in);
         System.out.println("请输入要删除的员工编号");
         int eno = in.nextInt();
         System.out.println("请输入要删除的员工姓名");
         String enmae = in.next();
         Connection conn = null;
         PreparedStatement pStmt = null;
 ​
         try {
             conn = DBUtils.getConnection();
             String sql = "DELETE FROM employee WHERE eno = ? AND ename = ?";
             pStmt = conn.prepareStatement(sql);
             pStmt.setInt(1,eno);
             pStmt.setString(2,enmae);
             int cnt = pStmt.executeUpdate();
             if (cnt == 1){
                 System.out.println("cnt:"+cnt);
                 System.out.println("员工编号"+eno+",姓名"+enmae+"的员工已删除");
             }else {
                 System.out.println("员工编号"+eno+",姓名"+enmae+"的员工未找到");
             }
 ​
         } catch (ClassNotFoundException e) {
             e.printStackTrace();
         } catch (SQLException throwables) {
             throwables.printStackTrace();
         }finally {
             DBUtils.closeConnection(null,pStmt,conn);
         }
     }
 }

更新和删除操作的方法主要区别是sql语句的不同,其它的内容大致相似。

JDBC的事务管理

JDBC中允许两种事务模式,分别是自动提交和手动提交模式

  • 自动提交事务模式

    • 自动提交模式是指每执行一次写操作SQL,自动提交事务

    • 自动提交开启方法:conn.setAutoCommit(true)

    • 自动事务是JDBC默认行为,此模式无法保证多数据一致性

  • 手动提交事务模式

    • 手动提交模式是指显式调用commit()与rollback()方法管理事务

    • 手动提交开启方法;conn.setAutoCommit(flase)

    • 手动提交事务可保证多数据一致性,但必须手动调用提交/回滚方法

//手动提交事务案例

 ​
 //JDBC事务管理,演示案例批量添加员工
 public class TransactionSample {
     public static void main(String[] args) {
         Connection conn = null;
         PreparedStatement pStmt = null;
 ​
         try {
             conn = DBUtils.getConnection();
             conn.setAutoCommit(false);//开启jdbc手动提交事务,,自动提交事务时默认为true
             String sql = "insert into employee(eno,ename,salary,dname) values(?,?,?,?)";
             pStmt = conn.prepareStatement(sql);
             for (int i=1000; i<2000; i++){
                 if (i==1005){
 //                    throw new RuntimeException("插入失败"); //注释后,不抛异常,正常执行
                 }
                 pStmt.setInt(1,i);
                 pStmt.setString(2,"员工"+i);
                 pStmt.setFloat(3,4000f);
                 pStmt.setString(4,"市场部");
                 pStmt.executeUpdate();
             }
             conn.commit();//手动提交情况下才能显式使用
         } catch (Exception e) {
             try {
                 conn.rollback();//回滚数据,手动提交情况下才能使用
             } catch (SQLException throwables) {
                 throwables.printStackTrace();
             }
         } finally {
             DBUtils.closeConnection(null,pStmt,conn);
         }
     }
 }
JDBC对时间类型的处理

//将String类型转为java.sql.Date,分为两步,分别是

         //1.String转为java.util.Date
         java.util.Date udHiredate = null;
         SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
         try {
             udHiredate = sdf.parse(strHireadate);
         } catch (ParseException e) {
             e.printStackTrace();
         }
         //2.java.util.Date转为java.sql.Date
         long time = udHiredate.getTime();//获取自1970到现在的毫秒数
         java.sql.Date sdHiredate = new java.sql.Date(time);

数据库连接池

阿里巴巴Druid连接池

Druid是阿里巴巴开源连接池组件,Druid对数据库连接进行有效管理与重用,最大化程序执行效率,连接池负责创建管理连接,程序只负责取用与归还

连接Druid连接池(配置和使用)
 //配置使用Druid连接池
 public class DruidSample {
     public static void main(String[] args) {
 ​
         //1.加载属性文件
         Properties properties = new Properties();
         String propertyFile = DruidSample.class.getResource("/druid-config.properties").getPath();
         try {
             propertyFile = new URLDecoder().decode(propertyFile, "UTF-8");//解析文件,避免错误
             properties.load(new FileInputStream(propertyFile));
         } catch (Exception e) {
             e.printStackTrace();
         }
         Connection conn = null;
         PreparedStatement pStmt = null;
         ResultSet rs = null;
 ​
         try {
             //2.获取DataSource数据源对象
             DataSource dataSource = DruidDataSourceFactory.createDataSource(properties);
             //创建数据库连接
             conn = dataSource.getConnection();
             pStmt = conn.prepareStatement("select * from employee limit 0,5");
             rs = pStmt.executeQuery();
             while(rs.next()){
                 Integer eno= rs.getInt(1);
                 String name = rs.getString("ename");
                 Float salary = rs.getFloat("salary");
                 String dname = rs.getString("dname");
                 Date hiredate = rs.getDate("hiredate");
                 System.out.println(eno+"-"+name+"-"+salary+"-"+dname+"-"+ hiredate);
             }
         } catch (Exception e) {
             e.printStackTrace();
         }finally {
             DBUtils.closeConnection(rs,pStmt,conn);
         }
 ​
     }
 }

Apache Commons DBUtils
  • commons-dbutils是Apache提供的开源JDBC工具类库

  • 它是对JDBC的简单封装,学习成本极低

  • 使用commons-dbutils可以极大简化JDBC编码工作量

  • 11
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

这啥呀

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值