[Java][华为云Java编程创造营][学习笔记][第三阶段][03_Java数据库实战]

举报
John2021 发表于 2021/12/05 09:28:02 2021/12/05
【摘要】 1,JDBC概述和接口 1.1,JDBC简介 什么是JDBC?Java Database ConnectivityJDBC是Java访问数据库的标准规范,真正怎么操作数据库还需要具体的实现类,也就是数据库驱动,每个数据库厂商根据自家数据库的通信格式编写好自己数据库的驱动。所以我们只需要会调用JDBC接口中的方法即可,数据库驱动由数据库厂商提供。 使用JDBC的好处程序员如果要开发访问数据库...

1,JDBC概述和接口

1.1,JDBC简介

什么是JDBC?

  • Java Database Connectivity
  • JDBC是Java访问数据库的标准规范,真正怎么操作数据库还需要具体的实现类,也就是数据库驱动,每个数据库厂商根据自家数据库的通信格式编写好自己数据库的驱动。所以我们只需要会调用JDBC接口中的方法即可,数据库驱动由数据库厂商提供。

使用JDBC的好处

  • 程序员如果要开发访问数据库的程序,只需要会调用JDBC接口中的方法即可,不用关注类是如何实现的。
  • 使用同一套Java代码,进行少量的修改就可以访问其他JDBC支持的数据库。

使用JDBC开发使用到的包

包名 内容概述
java.sql 所有与JDBC访问数据库相关的接口和类
javax.sql 数据库拓展包,提供数据库额外的功能。比如:连接池
数据库的驱动 由各大数据库厂商提供,需要额外去下载,是对JDBC接口实现的类

JDBC核心API

接口或类 作用
DriverManager类 1,管理和注册数据库驱动。2,得到数据库连接对象。
Connection接口 一个连接对象,可用于创建Statement和PreparedStatement对象
Statement接口 一个SQL语句对象,用于将SQL语句发送给数据库服务器
PreparedStatement接口 一个SQL语句对象,是Statement的子接口
ResultSet接口 用于封装数据库查询的结果集,返回给客户端Java程序

1.2,JDBC对象之DriverManage

JDBC访问数据库的步骤

定义(DriverManager:驱动管理器)

  • 注册驱动:这可以让JDBC知道要使用的是哪个驱动。
  • 获取Connection:如果可以获取到Connection,那么说明已经与数据库连接上了。

创建连接

  • DriverManager负责驱动程序管理,数据库驱动则是为了应用程序服务的,所以DriverManager的重要任务就是提供连接的获取。

驱动程序查找

  • DriverManager管理驱动程序,不仅仅提供了借助于驱动程序创建连接的能力,还能够返回给定的Driver或者Driver列表。

DriverManager常用方法

1.3,JDBC对象之Connection

定义

  • Connection对象表示连接,与数据库的通讯都是通过这个对象展开的。
  • Connection最为重要的一个方法就是用来获取Statement对象。

执行对象

  • 用于将SQL语句发送到数据库中。

执行对象有3种

  • Statement:用于执行静态SQL语句并返回其生成的结果的对象。
  • PreparedStatement:表示预编译的SQL语句的对象。
  • CallableStatement:用于执行SQL存储过程的对象。

事务

  • Connection提供了对于事务相关操作的支持。

重点方法简介

  • 静态执行对象创建createStatement
Statement createStatement() 创建一个Statement对象,用于将SQL语句发送到数据库
  • 动态执行对象创建prepareStatement
PreparedStatement prepareStatement(String sql) 创建一个PreparedStatement对象,用于将参数化的SQL语句发送到数据库
  • 存储过程执行对象创建CallableStatement
CallableStatement prepareCall(String sql) 创建一个CallableStatement对象来调用数据库存储过程

1.4,JDBC对象之Statement

定义

  • Statement是用来向数据库发送SQL语句的,这样数据库就会执行发送过来的SQL语句。
  • void executeUpdate(String sql):执行更新操作(insert、update、delete等)
  • ResultSet executeQuery(String sql):执行查询操作,数据库在执行查询后会把查询结果返回,查询结果就是ResultSet。

执行对象有3种

  • Statement继承自Wrapper。
  • PreparedStatement继承自Statement。
  • CallableStatement继承自PreparedStatement。

继承关系图

区别与联系

  • Statement接口:提供了执行语句和获取结果的基本方法。使用场景:普通的不带参数的查询SQL (带参数可能会造成SQL注入攻击)。
  • PreparedStatement接口:添加了处理输入参数的方法。使用场景:支持可变参数的SQL。
  • CallableStatement接口:添加了调用存储过程函数以及处理输出参数的方法。使用场景: 支持调用存储过程,提供了对输出和输入/输出参数(INOUT)的支持。
  • 这三种执行对象,都是为执行SQL而生,所以他们的重中之重全都是执行SQL。

1.5,JDBC对象之ResultSet

定义

  • ResultSet对象表示查询结果集,只有在执行查询操作后才会有结果集的产生;结果集是一个二维的表格,有行有列,通过移动ResultSet结果集内部的"行光标",获取当前行上的每一列上的数据。

常用API方法

  • boolean next():使"行光标"移动到下一行,并返回移动后的行是否存在。
  • XXX getXXX(int col):获取当前行指定列上的值,参数就是列表,列数从1开始,而不是0。

ResultSet结果集的遍历方式


2,JDBC连接数据库

2.1,连接Oracle数据库

  • 1,添加Oracle驱动的Maven依赖
<dependencies>
    <dependency>
        <groupId>com.oracle</groupId>
        <artifactId>ojdbc6<artifactId>
        <version>11.2.0.3</version>
    </dependency>
</dependencies>
  • 2,加载和注册Oracle驱动
public class TestOracle
{
    public static void main(String[] args) throws Exception
    {
        try
        {
            Class.forName("oracle.jdbc.driver.oracleDriver");
        } catch (ClassNotFoundException e)
        {
            e.printStackTrace();
        }
    }
}
  • 3,通过DriverManager获取连接对象
import java.sql.Connection;
import java.sql.DriverManager;

public class TestDriverManager
{
    public static void main(String[] args) throws Exception
    {
        Connection connection = DriverManager.getConnection("jdbc:oracle:thin:@127.0.0.1:1521:orcl", "scott", "1234");
    }
}

2.2,连接MySQL数据库

  • 1,添加MySQL驱动的Maven依赖
<dependencies>
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>5.1.47<version>
    </dependency>
</dependencies>
  • 2,加载和注册MySQL驱动
public class TestMySQL
{
    public static void main(String[] args) throws Exception
    {
        try
        {
            Class.forName("com.mysql.jdbc.Driver");
        } catch (ClassNotFoundException e)
        {
            e.printStackTrace();
        }
    }
}
  • 3,通过DriverManager获取连接对象
import java.sql.Connection;
import java.sql.DriverManager;

public class TestDriverManager
{
    public static void main(String[] args) throws Exception
    {
        Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb", "root", "1234");
    }
}

2.3,Statement接口和操作

Statement常用方法

Statement接口中的方法 描述
int executeUpdate(String sql) 用于发送DML语句,增删改的操作:insert,update,delete;参数:SQL语句;返回值:返回对象数据库影响的行数
ResultSet executeQuery(String sql) 用于发送DQL语句,执行查询的操作:select;参数:SQL语句;返回值:查询的结果集
void close() 立即释放此Statement对象占用的数据库和JDBC资源。

JDBC使用Statement操作数据的步骤

  • 1,使用Connection获取Statement对象
  • 2,创建SQL语句
  • 3,使用Statement对象执行SQL语句
  • 4,关闭连接,释放资源
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;

public class Test
{
    public static void main(String[] args) throws Exception
    {
        //通过类加载的方式加载数据库驱动
        //参数:数据库驱动实现类的反射路径
        Class.forName("oracle.jdbc.driver.OracleDriver");
        //通过DriverManager获取Connection连接对象
        Connection conn = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:orcl", "scott", "1234");
        //获取发送sql语句的对象:statement
        Statement stmt = conn.createStatement();
        //创建SQL语句
        String sql = "insert into dept values (10,'部门','城市')";
        //把SQL语句发送到数据库执行
        //executeUpdate:执行增删改操作
        //i:表示增删改影响的行数
        int i = stmt.executeUpdate(sql);
        if (i > 0)
        {
            System.out.println("成功插入[" + i + "]条记录");
        } else
        {
            System.out.println("插入失败");
        }
        //关闭连接,释放资源
        stmt.close();
        conn.close();
    }
}

JDBC使用Statement查询数据的步骤

  • 1,使用Connection获取Statement对象
  • 2,创建SQL语句
  • 3,使用Statement对象执行SQL语句
  • 4,执行查询数据操作,得到ResultSet结果集对象
  • 5,对结果集对象进行遍历,取出每一条记录
  • 6,关闭连接,释放资源
import java.sql.*;

public class Test
{
    public static void main(String[] args) throws Exception
    {
        //通过类加载的方式加载数据库驱动
        //参数:数据库驱动实现类的反射路径
        Class.forName("oracle.jdbc.driver.OracleDriver");
        //通过DriverManager获取Connection连接对象
        Connection conn = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:orcl", "scott", "1234");
        //获取发送sql语句的对象:statement
        Statement stmt = conn.createStatement();
        //创建sql语句
        String sql = "select * from dept ";
        //把SQL语句发送到数据库执行 - executeQuery:表示查询操作
        //返回结果集对象:ResultSet
        ResultSet rs = stmt.executeQuery(sql);
        //next():当调用next()的时候,游标会向下移动一行
        //返回boolean类型,如果没有下一行了,返回false
        while (rs.next())
        {
            /*
             * 获取数据的方式
             * 1,通过get数据类型(行下标)
             * 2,通过get数据类型("列的名字")
             * */
            System.out.println(rs.getInt(1) + "," +
                    rs.getString("dname") + "," + rs.getString(3));
        }
        //关闭连接,释放资源
        rs.close();
        stmt.close();
        conn.close();
    }
}

ResultSet常用方法

ResultSet接口中的方法 描述
boolean next() 1,游标向下移动1行。2,返回boolean类型,如果还有下一条记录,返回true,否则返回false。
数据类型 getxxx() 1,通过字段名获取数据,参数是String类型,返回不同的类型。2,通过列号获取数据,参数是整数,从1开始。返回不同的类型。

ResultSet接口获取结果集中字段数据的方法

boolean getBoolean(int columnIndex) 检索该ResultSet对象的当前行中指定列的值为Java中的boolean
boolean getBoolean(String columnLabel) 检索该ResultSet对象的当前行中指定列的值为Java中的boolean
byte getByte(int columnIndex) 检索此ResultSet对象当前行中指定列的值为Java中的byte
byte getByte(String columnLabel) 以Java中的byte 此ResultSet对象的当前行中指定列的值
double getDouble(int columnIndex) 以Java中的double 此ResultSet对象的当前行中指定列的值
double getDouble(String columnLabel) 以Java中的double 此ResultSet对象的当前行中指定列的值

小结

ResultSet接口获取数据的注意事项

  • 如果光标在第一行之前,使用rs.getxxx()获取列值,会报Before start of result set的错误。
  • 如果光标在最后一行之前,使用rs.getxxx()获取列值,会报After end of result set的错误。

关闭连接,释放资源时需要注意的问题

  • 需要释放的对象:ResultSet结果集、Statement语句、Connection连接。
  • 释放原则:先关闭结果集ResultSet,再关闭Statement,最后关闭Connection。
  • 代码位置:放在finally语句块中。

2.4,PreparedStatement接口和操作

为什么要使用PreparedStatement?

  • 案例:用户登录(在控制台输入用户名和密码,如果和数据库中的数据匹配成功,则登录成功,否则登录失败)
  • SQL注入问题(当我们输入以下密码,我们发现我们账号和密码都不对竟然登录成功了)
请输入用户名:
newboy
请输入密码:
a' or '1'='1

select * from user where name='newboy' and password='a' or '1'='1'

登录成功,欢迎你:newboy

产生SQL注入问题的原因

  • 1,我们让用户输入的密码和SQL语句进行字符串拼接。用户输入的内容作为了SQL语句语法的一部分,改变了原有SQL真正的意义,以上问题称为SQL注入。
  • 2,要解决SQL注入就不能让用户输入的密码和我们的SQL语句进行简单的字符串拼接。

预编译对象解决SQL注入问题

  • 1,使用占位符?来创建SQL语句,当创建预编译对象的时候,就提前把SQL语句发送到数据库保存(缓存),数据库获取到该SQL语句的结构,无法再修改。
  • 2,执行查询的时候,发送的不是SQL语句,而是占位符的值。

定义

  • PreparedStatement是Statement接口的子接口,继承于父接口中所有的方法,它是一个预编译的SQL语句。

PreparedStatement的作用和执行原理

  • 因为有预先编译(缓存)的功能,提高SQL的执行效率。

  • 参数化,防止SQL注入。

  • 提高了程序的可读性。

PreparedStatement常用方法

Connection接口中的方法 描述
PreparedStatement preparedStatement(String sql) 指定预编译的SQL语句,SQL语句中使用占位符?创建一个语句对象
PreparedStatement中设置的参数的方法 描述
void setDouble(int parameterIndex,double x) 将指定参数设置为给定Java Double值
void setInt(int parameterIndex,int x) 将指定参数设置为给定Java int值
void setLong(int parameterIndex,long x) 将指定参数设置为给定Java long值
void setObject(int parameterIndex,Object x) 使用给定对象设置指定参数的值
void setString(int parameterIndex,String x) 将指定参数设置为给定Java String值

JDBC使用PreparedStatement查询数据的步骤

  • 1,编写SQL语句,未知内容使用?占位
  • 2,获得PreparedStatement对象
  • 3,给占位符设置值
  • 4,执行查询数据操作,得到ResultSet结果集对象
  • 5,对结果集进行处理
  • 6,释放资源
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;

public class Test
{
    public static void main(String[] args) throws Exception
    {
        //创建SQL语句
        String sql = "select * from hw_user where name = ? and password =?";
        //创建连接对象
        Connection connection = DriverManager.getConnection("");
        //创建预编译对象
        PreparedStatement preparedStatement = connection.prepareStatement(sql);
        //给占位符设置值
        //语法:set数据类型(占位符的位置,占位符的值)
        preparedStatement.setString(1, username);
        preparedStatement.setString(2, userpassword);
        //执行查询
        //注意:这里不能再添加sql参数了
        ResultSet resultSet = preparedStatement.executeQuery();
        System.out.println("sql:" + sql);
        if (resultSet.next())
        {
            System.out.println("登录成功");
        } else
        {
            System.out.println("登录失败");
        }
    }
}

2.5,CallableStatement接口和操作

  • CallableStatement和PreparedStatement一样也是Statement接口的子接口,其主要作用是调用存储过程。

CallableStatement的主要方法如下:

CallableStatement常用方法 描述
String getString(String parameterName) 根据参数名称获取调用存储过程返回的值
String getString(int parameterIndex) 根据编号获取调用存储过程返回的值
void setObject(String parameterName,Object x) 给存储过程中的输入参数设置值
registerOutParameter(String parameterName,int sqlType) 给存储过程中的输出参数设置值
execute() 执行存储过程

JDBC使用CallableStatement调用存储过程操作数据的步骤:

  • 1,创建callableStatement对象:CallableStatement call=connection.prepareCall("{call 存储过程名(?,?,?)}");
  • 2,设置传入参数的值:call.set参数类型(int index,参数值);
  • 3,设置传出参数的值:call.registerOutParameter(int index,Types.数据类型);
  • 4,执行操作存储过程:call.execute();
  • 5,得到返回的输出参数的值:call.getObject(参数序号);

JDBC使用CallableStatement调用存储过程完整示例

import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

public class Test
{
    public static void main(String[] args) throws Exception
    {
        Connection connection = null;
        CallableStatement callableStatement = null;
        try
        {
            //通过类加载的方式加载数据库驱动
            //参数,数据库驱动实现类的反射路径
            Class.forName("oracle.jdbc.driver.OracleDriver");
            //通过DriverManager获取Connection连接对象
            connection = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:orcl", "scott", "1234");
            callableStatement = connection.prepareCall("{call emp_pro(?,?,?)}");
            callableStatement.setString(1, "CLERK");
            callableStatement.setInt(2, 20);
            callableStatement.registerOutParameter(3, OracleTypes.NUMBER);
            callableStatement.execute();
            System.out.println("员工个数为:" + callableStatement.getObject(3));
        } catch (Exception e)
        {
            e.printStackTrace();
        } finally
        {
            try
            {
                callableStatement.close();
                connection.close();
            } catch (SQLException e)
            {
                e.printStackTrace();
            }
        }
    }
}

3,JDBC对数据库的增删改查

3.1,JDBC增删改查Oracle数据库

JDBC增删改查Oracle数据库(1)

使用JDBC向Oracle数据库中进行添加数据操作

案例:向部门表(Dept)添加一条记录
实现步骤
  • 1,加载驱动程序
  • 2,通过DriverManager获取Connection连接对象
  • 3,创建SQL语句并且创建预编译对象
  • 4,给占位符设置值
  • 5,执行插入操作
  • 6,关闭数据库连接,释放资源
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;

public class Test
{
    public static void main(String[] args) throws Exception
    {
        //1,通过类加载的方式加载数据库驱动
        Class.forName("oracle.jdbc.Driver.OracleDriver");
        //2,通过DriverManager获取Connection连接对象
        Connection connection = DriverManager.getConnection("jdbc:oracle:thin:@127.0.0.1:1521:orcl", "scott", "1234");
        //3,创建SQL语句并且创建预编译对象
        PreparedStatement ps = connection.prepareStatement("insert into dept "
                + "values (seq_dept.nextval,?,?)");
        //4,给占位符设置值
        ps.setString(1, "市场部");
        ps.setString(2, "北京");
        //5,执行插入操作
        int i = ps.executeUpdate();
        System.out.println("i=" + i);
        //6,关闭数据库连接,释放资源
        ps.close();
        connection.close();
    }
}

JDBC增删改查Oracle数据库(2)

使用JDBC对Oracle数据库进行修改数据操作

案例:操作员工表(Emp),把员工"ALLEN"的工资上调500,奖金上调100.
实现步骤:
  • 1,加载驱动程序
  • 2,通过DriverManager获取Connection连接对象
  • 3,创建SQL语句并且创建预编译对象
  • 4,给占位符设置值
  • 5,执行修改操作
  • 6,关闭数据库连接,释放资源
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;

public class Test
{
    public static void main(String[] args) throws Exception
    {
        //1,通过类加载的方式加载数据库服务
        Class.forName("oracle.jdbc.driver.OracleDriver");
        //2,通过DriverManager获取Connection连接对象
        Connection connection = DriverManager.getConnection("jdbc:oracle:thin:@127.0.0.1:1521:orcl", "scott", "1234");
        //3,创建SQL语句并且创建预编译的对象
        PreparedStatement ps = connection.prepareStatement("update emp set sal= = sal + ?,"
                + "comm = comm + ? where ename = ?");
        //4,给占位符设置值
        ps.setDouble(1, 500);
        ps.setDouble(2, 100);
        ps.setString(3, "ALLEN");
        //5,执行更新操作
        int i = ps.executeUpdate();
        System.out.println("i: " + i);
        //6,关闭数据库连接,释放资源
        ps.close();
        connection.close();
    }
}

JDBC增删改查Oracle数据库(3)

使用JDBC对Oracle数据库进行删除数据操作

案例:操作员工表(Emp),把编号为"7934"的员工删除
实现步骤:
  • 1,加载驱动程序
  • 2,通过DriverManager获取Connection连接对象
  • 3,创建SQL语句并且创建预编译对象
  • 4,给占位符设置值
  • 5,执行修改操作
  • 6,关闭数据库连接,释放资源
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;

public class Test
{
    public static void main(String[] args) throws Exception
    {
        //1,通过类加载的方式加载数据库驱动
        Class.forName("oracle.jdbc.driver.OracleDriver");
        //2,通过DriverManager获取Connection连接对象
        Connection connection = DriverManager.getConnection("jdbc:oracle:thin:@127.0.0.1:1521:orcl", "scott", "1234");
        //3,创建SQL语句并创建预编译的对象
        PreparedStatement ps = connection.prepareStatement("delete from emp where enmpno = ?");
        //4,给占位符赋值
        ps.setInt(1, 7934);
        //5,执行删除操作
        int i = ps.executeUpdate();
        System.out.println("i: " + i);
        //6,关闭数据库连接,释放资源
        ps.close();
        connection.close();
    }
}

JDBC增删改查Oracle数据库(4)

使用JDBC对Oracle数据库进行查询数据操作

案例:操作员工表(Emp),根据员工姓名(模糊查询),职位,入职时间,所属部门查询员工信息。
实现步骤:
  • 1,加载驱动程序
  • 2,通过DriverManager获取Connection连接对象
  • 3,创建SQL语句并且创建预编译对象
  • 4,给占位符设置值
  • 5,执行修改操作
  • 6,关闭数据库连接,释放资源
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.*;

public class Test1
{
    public static void main(String[] args) throws Exception
    {
        //1,通过类加载的方式加载数据库驱动
        Class.forName("oracle.jdbc.driver.OracleDriver");
        //2,通过DriverManager获取Connection连接对象
        Connection conn1 = DriverManager.getConnection("jdbc:oracle:thin:@127.0.0.1:1521:orcl", "scott", "1234");
        //3,创建SQL语句并且创建预编译的对象
        PreparedStatement ps1 = conn1.prepareStatement("select * from emp where ename like ? "
                + "and job = ? and hiredate >= ? and deptno = ?");
        //4,给占位符赋值
        ps1.setString(1, "%d%");
        ps1.setString(2, "CLERK");
        ps1.setDate(3, Date.valueOf("2021-12-03"));
        ps1.setInt(4, 20);
        //5,执行查询操作
        ResultSet rs = ps1.executeQuery();
        while (rs.next())
        {
            System.out.println(rs.getInt(1) + " - " + rs.getString(2) + " - " + rs.getString(3));
        }
        //6,关闭数据库连接,释放资源
        rs.close();
        ps1.close();
        conn1.close();
    }
}

3.2,JDBC增删改查MySQL数据库

JDBC增删改查MySQL数据库(1)

使用JDBC向MySQL数据库中进行添加数据操作

案例:向图书表(book_info)添加一条记录
实现步骤:
  • 1,获取数据库连接对象
  • 2,创建SQL语句并且创建预编译的对象
  • 3,给占位符设置值
  • 4,执行插入操作
  • 5,关闭连接,释放资源
import java.sql.*;

public class Test
{
    public static void main(String[] args) throws Exception
    {
        //1,通过类加载方式加载数据库驱动
        Class.forName("com.mysql.jdbc.Driver");
        //2,通过DriverManager获取Connection连接对象
        Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/bookstore?characterEncoding=utf8", "root", "1234");
        //3,创建SQL语句并创建预编译对象
        PreparedStatement ps = conn.prepareStatement("insert into book_info values (null,?,?,?,?,?,?,?)");
        //4,给占位符赋值
        ps.setString(1, "GBK_005");
        ps.setString(2, "Thinking in Java");
        ps.setInt(3, 8);
        ps.setString(4, "埃克尔");
        ps.setString(5, "机械工业出版社");
        ps.setDate(6, Date.valueOf("2021-12-03"));
        ps.setInt(7, 1);
        //5,执行插入操作
        int i = ps.executeUpdate();
        //6,关闭连接,释放资源
        ps.close();
        conn.close();
        System.out.println("i: " + i);
    }
}

JDBC增删改查MySQL数据库(2)

MySQL数据库和Oracle数据库插入数据的去比:

  • 当MySQL数据库插入数据时,想实现主键的自动增长时,不需要创建序列。

  • 可以使用2种方式进行占位符的设置:

    • 把主键的位置设置为null
      insert into book_info values (null,?,?,...)
    • 把主键的位置设置为当前表中的字段名
      insert into book_info values (book_id,?,?,...)

JDBC增删改查MySQL数据库(3)

使用JDBC对MySQL数据库进行修改数据操作

案例:操作图书表(book_info),把图书编号为"GBK_001"的图书的出版社修改为"少年儿童出版社"
实现步骤:
  • 1,获取数据库连接对象
  • 2,创建SQL语句并且创建预编译对象
  • 3,给占位符赋值
  • 4,执行修改操作
  • 5,关闭连接,释放资源
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;

public class Test
{
    public static void main(String[] args) throws Exception
    {
        Class.forName("com.mysql.jdbc.Driver");
        Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/bookstore?characterEncoding=utf8", "root", "1234");
        PreparedStatement ps = conn.prepareStatement("update book_info set publish_press = ? where book_code = ?");
        ps.setString(1, "少年儿童出版社");
        ps.setString(2, "GBK_001");
        int i = ps.executeUpdate();
        ps.close();
        conn.close();
        System.out.println("i: " + i);
    }
}

JDBC增删改查MySQL数据库(4)

使用JDBC对MySQL数据库进行删除数据操作

案例:操作图书表(book_info),删除图书编号为"YS_001"的图书信息
实现步骤:
  • 1,获取数据库连接对象
  • 2,创建SQL语句并且创建预编译对象
  • 3,给占位符设置值
  • 4,执行删除操作
  • 5,关闭连接,释放资源
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;

public class Test
{
    public static void main(String[] args) throws Exception
    {
        Class.forName("com.mysql.jdbc.Driver");
        Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/bookstore?characterEncoding=utf8", "root", "1234");
        PreparedStatement ps = conn.prepareStatement("delete from book_info where book_code = ?");
        ps.setString(1, "YS_001");
        int i = ps.executeUpdate();
        ps.close();
        conn.close();
        System.out.println("i: " + i);
    }
}

JDBC增删改查MySQL数据库(5)

使用JDBC对MySQL数据库进行查询数据操作

案例:操作图书表(book_info),查询"人民教育出版社"出版的图书信息,并且显示图书的类型名称。
分析:图书表(book_info)和图书分类表(book_type)需要做关联查询
实现步骤:
  • 1,获取数据库连接对象
  • 2,创建SQL语句并且创建预编译对象
  • 3,给占位符设置值
  • 4,执行查询操作
  • 5,遍历结果集,输出图书信息
  • 6,关闭连接,释放资源
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;

public class Test
{
    public static void main(String[] args) throws Exception
    {
        Class.forName("com.mysql.jdbc.Drvier");
        Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/bookstore?characterEncoding=utf8", "root", "1234");
        String sql = "select b.*,t.`type_name` " +
                "from book_info b " +
                "inner join book_type t on b.`book_type` = t.`id` " +
                "where b.`publish_press` = ?";
        PreparedStatement ps = conn.prepareStatement(sql);
        ps.setString(1, "人民教育出版社");
        ResultSet rs = ps.executeQuery();
        while (rs.next())
        {
            //获取部分字段值
            System.out.println(rs.getInt(1) + "," + rs.getString(2) + "," + rs.getString(3) + "," + rs.getString("type_name"));
        }
        rs.close();
        ps.close();
        conn.close();
    }
}

JDBC增删改查MySQL数据库(6)

使用JDBC向MySQL数据库中进行批量插入数据操作

  • Java的批量操作机制允许多条语句一次性提交给数据库批量处理,通常情况下比单独提交处理更有效率。

JDBC的批量处理语句包括下面三个方法

PreparedStatement的方法名 内容概述
void addBatch() 向这个PreparedStatement对象的一批命令添加一组参数。
Statement的方法名 内容概述
void clearBatch() 清空这个Statement对象当前的SQL命令列表。
int[] executeBatch() 将一批命令提交到数据库以执行,并且所有命令都执行成功,返回一个更新计数的数组。

案例:使用JDBC向MySQL的customers数据表中插入10万条记录,测试如何插入用时最短。

实现步骤:

  • 1,使用PreparedStatement的非批量操作方式,测试插入时间。
  • 2,使用Batch批量操作,测试插入时间。

总结:

  • 通过对比插入数据程序耗费的时间,发现使用Batch批量操作,提高了插入数据的效率。
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.util.Date;

public class Test
{
    Connection conn = null;
    PreparedStatement ps = null;

    public static void main(String[] args) throws Exception
    {
        Class.forName("com.mysql.jdbc.Drvier");
        conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/bookstore?characterEncoding=utf8", "root", "1234");
        conn.setAutoCommit(false);
        ps = conn.prepareStatement("insert into customers values (?,?,?)");
        Date date = new Date(date.getTime());
        long begin = System.currentTimeMillis();
        for (int i = 1; i < 100009; i++)
        {
            ps.setInt(1, i);
            ps.setString(2, "name_" + i);
            ps.setDate(3, date);
            ps.addBatch();
            if (i % 300 == 0)
            {
                ps.executeBatch();
                ps.clearBatch();
            }
        }
        if (100009 % 300 != 0)
        {
            ps.executeBatch();
            ps.clearBatch();
        }
        long end = System.currentTimeMillis();
        System.out.println("Time: " + (end - begin));
        conn.commit();
    }
}

3.3,JDBC使用数组封装自定义操作工具类

JDBC使用数组封装自定义操作工具类(1)

创建JDBCUtils数据库连接工具类

什么是工具类?
  • 如果一个功能经常要用到,我们建议把这个功能做成一个工具类,可以在不同的地方重用。
实现步骤:
  • 1,把用户名、密码、URL、驱动类定义成静态变量。
  • 2,通过静态代码块加载数据库驱动
  • 3,创建获取数据库连接的方法
  • 4,创建关闭连接,释放资源的方法(可以使用方法的重载)

JDBC使用数组封装自定义操作工具类(2)

工具类JDBCUtils的核心代码(1)

import java.sql.*;

public class Test
{
    private static String className = "com.mysql.jdbc.Driver";
    private static String url = "jdbc:mysql://localhost:3306/bookstore?characterEncoding=utf8";
    private static String username = "root";
    private static String password = "1234";

    static
    {
        //加载驱动程序
        try
        {
            Class.forName(className);
        } catch (ClassNotFoundException e)
        {
            e.printStackTrace();
        }
    }

    //获取数据库连接对象
    public static Connection getConn()
    {
        try
        {
            return DriverManager.getConnection(url, username, password);
        } catch (SQLException e)
        {
            e.printStackTrace();
            throw new RuntimeException("数据库连接错误");
        }
    }
}

JDBC使用数组封装自定义操作工具类(3)

工具类JDBCUtils的核心代码(2)

public class Test
{
    private static String className = "com.mysql.jdbc.Driver";
    private static String url = "jdbc:mysql://localhost:3306/bookstore?characterEncoding=utf8";
    private static String username = "root";
    private static String password = "1234";

    //关闭连接,释放资源
    public static void closeAll(Connection conn, Statement stmt, ResultSet rs)
    {
        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();
            }
        }
    }

    //方法的重载实现
    public static void closeAll(Connection conn, Statement stmt)
    {
        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 closeAll(Connection conn)
    {
        if (conn != null)
        {
            try
            {
                conn.close();
            } catch (SQLException e)
            {
                e.printStackTrace();
            }
        }
    }
}

JDBC使用数组封装自定义操作工具类(4)

使用DAO工具类来封装增删改查的操作

什么是DAO模式?
  • DAO(Data Access Object数据存取对象)是指位于业务逻辑和持久化数据之间实现对持久化数据的访问。通俗来讲,就是将数据库操作封装起来。
一个典型的DAO模式主要由以下几部分组成
  • DAO接口:把对数据库的所有操作定义成抽象方法,可以提供多种实现。
  • DAO实现类:针对不同数据库给出DAO接口定义方法的具体实现。
  • 实体类:用于存放与传输对象数据
实现步骤:
  • 1,创建包名:DAO
  • 2,创建CRUD的工具类接口:实体类名+Dao
  • 3,在接口中定义CRUD的抽象方法
  • 4,创建CRUD的工具类实现类:实体类名+Dao+Impl

JDBC使用数组封装自定义操作工具类(5)

案例:使用工具类来封装图书表(BookInfo),进行增删改查的操作

实现步骤:

  • 1,创建接口,定义抽象方法
public interface BookInterface
{
    //增加图书信息
    int addBookInfo(BookInfo bookInfo) throws Exception;

    //修改图书信息
    int updateBookInfo(String bookCode, String publishPress) throws Exception;

    //删除图书信息
    int deleteBookInfo(String bookCode) throws Exception;

    //查询图书信息
    BookInfo[] getBookInfo(String publishPress) throws Exception;
}
  • 2,创建实现类,实现接口中的抽象方法。
public class BookInfoDaoImpl implements BookInfoDao
{
    public int addBookInfo(BookInfo bookInfo) throws Exception;

    public int updateBookInfo(String bookCode, String publishPress) throws Exception;

    public int deleteBookInfo(String bookCode) throws Exception;

    public BookInfo[] getBookInfo(String publishPress) throws Exception;
}

JDBC使用数组封装自定义操作工具类(6)

  • 把增删改查的代码,可以提取到JDBCUtils中,对参数使用数组进行封装,代码更简洁。
  • JDBCUtils工具类优化增删改核心代码:
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;

public class Test
{
    public static int executeUpdate(String preparedSql, Object[] param) throws ClassNotFoundException
    {
        Connection conn = null;
        PreparedStatement pstmt = null;
        int count = 0;
        //处理SQL,执行SQL
        try
        {
            conn = pstmt.getConnection();//得到数据库连接
            pstmt = conn.prepareStatement(preparedSql);//得到PreparedStatement对象
            if (param != null)
            {
                for (int i = 0; i < param.length; i++)
                {
                    pstmt.setObject(i + 1, param[i]);//为预编译SQL设置参数
                }
            }
            count = pstmt.executeUpdate();//执行SQL语句
        } catch (SQLException e)
        {
            e.printStackTrace();//处理SQLException异常
        } finally
        {
            pstmt.close();
            conn.close();
        }
        return count;
    }
}

3.4,面向对象继承和重写实现多数据库操作

面向对象继承和重写实现多数据库操作实现步骤

//1,创建抽象类BaseDao
public abstract class BaseDao
{
    //2,创建CRUD的抽象方法
    public abstract Object[] queryEmpByCondition(Emp emp) throws Exception;

    public abstract int updateEmpById(Integer empno, Double sal) throws Exception;

    public abstract int delEmpById(Integer empno) throws Exception;

    public abstract int insertEmp(Emp emp) throws Exception;
}

//3,创建类,继承BaseDao,重写抽象方法
public class MySqlDaoImpl extends BaseDao
{
    //...
}

//4,创建类,继承BaseDao,重写抽象方法
public class OracleDaoImpl extends BaseDao
{
    //...
}
【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。