【Java实战项目】【超详细过程】—大饼的图片服务器3(ImageDao类详解)


本文主要是对ImageDao类的详细讲解,对数据库进行的增删查操作进行了细致的解释(包含:向数据库中写入一个图片属性信息,查找数据库中全部图片属性信息信息,查找数据库中部分图片属性信息,删除数据库中图片属性信息),并且定义了一个JavaImageServerException的异常类。


一、向数据库中写入图片属性

向数据库中插入数据可以分为以下步骤
1.与数据库建立连接
2.创建并拼接SQL语句
3.执行SQL语句
4.关闭数据库连接

1.与数据库建立连接

Connection connection = DBUtil.getConnection();

(1)使用DBUtil类的getConnection()方法创建了一个Connection数据库连接对象connection的变量,并将返回值储存在connection中。
(2)Connection对象是Java中用于与数据库进行交互的主要接口之一。通过这个对象,你可以执行SQL查询、更新和删除操作等。
(3)DBUtil是一个自定义的工具类,包含了管理数据库连接和数据库的一些基本属性,如:数据库名,密码等

2.创建并拼接SQL语句

String SQL = "INSERT INTO image VALUES(null,?,?,?,?,?,?)";
PreparedStatement statement = connection.prepareStatement(SQL);

(1)String SQL = "INSERT INTO image VALUES(null,?,?,?,?,?,?)";
SQL语句中?为占位符,根据数据库设计中可以得出:表中一共有7种属性,其中imageId为自增的,所以我们在向数据库中写入数据时不需要手动获取imageId,所以第一位为空,后面每一个?代表一个占位符

在这里插入图片描述

(2)PreparedStatement statement = connection.prepareStatement(SQL);
创建了一个steam对象用于执行预编译的 SQL 语句
prepareStatement() 方法是 Connection 类的一个方法,用于创建一个 PreparedStatement 对象。
PreparedStatement 还对象允许我们向数据库发送 SQL 查询,从而有助于防止 SQL 注入攻击。它还允许我们多次使用相同的 SQL 语句和不同的参数。

注意:
记得处理异常:try/catch
处理完异常后的代码:

        String SQL = "INSERT INTO image VALUES(null,?,?,?,?,?,?)";
        PreparedStatement statement = null;
        try {
            statement = connection.prepareStatement(SQL);
        } catch (SQLException e) {
            throw new RuntimeException(e);

3.执行SQL语句

            statement.setString(1,image.getImageName());
            statement.setInt(2,image.getSize());
            statement.setString(3,image.getUploadTime());
            statement.setString(4,image.getContentType());
            statement.setString(5,image.getPath());
            statement.setString(6,image.getMd5());
            
            int ret = statement.executeUpdate();
            if(ret != 1){
                //ret不等于1时代表SQL语句执行失败,此时应该抛出一个异常
                throw new JavaImageServerException("插入数据库出错");
            }

(1)statement.setString(1,image.getImageName());

statement对象使用SetString方法获取image对象的imageId属性的值,并将其赋值给statement对象的第一个占位符处,也就是SQL语句中的第一个?

(2)int ret = statement.executeUpdate(); ...

这段代码是使用 JDBC API 执行 SQL 语句并返回受影响的行数。
其中,statement 是一个 Statement 对象,表示要执行的 SQL 语句;executeUpdate() 方法用于执行 SQL 语句,并返回受影响的行数。
ret 变量将保存执行 SQL 语句后受影响的行数。如果成功插入了一条数据,那么ret将为1,因为插入一条数据数据库中受影响的数据行数为1

(3)注意处理异常,同样使用try/catch,可以将catch内容合并
(4)throw new JavaImageServerException("插入数据库出错");

此处使用了一个一异常类 JavaImageServerException ,表示在ret不等于1 即插入的SQL执行失败时(执行的时候数据库中受影响的数据行数不为1)返回一个异常,并通过try/catch块来捕获并处理该异常,打印出相应的错误消息

4.定义异常类JavaImageServerException

在Java目录下定义一个common包,在common包中定义JavaImageServerException,该类继承自Java内置的Exception类
该类有一个构造方法JavaImageServerException(String message),该构造方法接受一个字符串参数message作为异常信息,并调用父类的构造函数将该信息传递给异常对象

package common;

public class JavaImageServerException extends Exception{
    public JavaImageServerException(String message){
        super(message);//调用父类的构造函数,将message返回给异常对象
    }
}

5.关闭数据库连接

DBUtil.close(connection,statement,null);

如果这个代码卸载try中有一定概率会执行不到,为了保证他一定会执行可以使用finally

6.写入图片的完整代码

    //新增数据或插入数据(把image对象插入数据库中)
    public void insert(Image image) throws SQLException {
        /*
        1.与数据库建立链接    Connection connection = DBUtil.getConnection();
        2.创建并拼接SQL语句   String SQL= " ";   PreparedStatement statement = connection.prepareStatement(SQL);注意处理异常try/catch
        3.执行SQL语句        statement.setString(1,image.getImageName());
        4.关闭数据库连接      DBUtil.close(connection,statement,null); 注意是否一定会执行此语句
        */
        //获取数据库连接:
        Connection connection = DBUtil.getConnection();
        //构造并拼接SQL语句
        String SQL = "INSERT INTO image VALUES(null,?,?,?,?,?,?)";
        PreparedStatement statement = null;
        try {
            statement = connection.prepareStatement(SQL);
            //这行代码是用于创建一个 PreparedStatement 对象,该对象使用连接对象和要执行的 SQL 语句进行初始化。
            //PreparedStatement 对象允许您向数据库发送 SQL 查询,从而有助于防止 SQL 注入攻击。它还允许您多次使用相同的 SQL 语句和不同的参数。
            //在这个例子中,SQL 语句存储在变量 SQL 中,连接对象存储在变量 connection 中。
            // 通过调用 connection 对象的 prepareStatement() 方法来创建一个新的 PreparedStatement 对象,并将其分配给变量 statement。
            statement.setString(1,image.getImageName());
            statement.setInt(2,image.getSize());
            statement.setString(3,image.getUploadTime());
            statement.setString(4,image.getContentType());
            statement.setString(5,image.getPath());
            statement.setString(6,image.getMd5());
            
            int ret = statement.executeUpdate();
            //这段代码是使用 JDBC API 执行 SQL 语句并返回受影响的行数。
            // 其中,statement 是一个 Statement 对象,表示要执行的 SQL 语句;executeUpdate() 方法用于执行 SQL 语句,并返回受影响的行数。
            // 在这个例子中,ret 变量将保存执行 SQL 语句后受影响的行数。如果执行成功,ret 的值将为正数,否则为负数。
            if(ret != 1){
                //ret不等于1时代表SQL语句执行失败,此时应该抛出一个异常
                throw new JavaImageServerException("插入数据库出错");
                //此处使用了一个一异常类 JavaImageServerException ,
                // 表示在ret不等于1 即插入的SQL执行失败时抛出一个JavaImageServerException异常,
                // 创建一个JavaImageServerException对象,并将“插入数据库出错”作为参数传给该异常的构造函数
                // 并通过try/catch块来捕获并处理该异常,打印出相应的错误消息
            }
        } catch (SQLException e) {
            throw new RuntimeException(e);
        } catch (JavaImageServerException e) {
            throw new RuntimeException(e);
        }finally {
            //关闭连接
            DBUtil.close(connection,statement,null);
        }
    }

二、查找数据库中所有图片属性

向数据库中插入数据可以分为以下步骤
1.与数据库建立连接
2.创建并拼接SQL语句
3.执行SQL语句
4.处理结果集
5.关闭数据库连接

1.与数据库建立连接

Connection connection = DBUtil.getConnection();//建立数据库连接

2.创建并拼接SQL语句

String SQL = "select *from image;";//构造SQL语言
PreparedStatement statement = null;//statement 用于拼接SQL语言
statement = connection.prepareStatement(SQL);//拼接SQL语言

(1)repareStatement(String sql)方法会将传入的SQL查询语句进行预编译,并将其转换为一个可执行的PreparedStatement对象,将创建的PreparedStatement对象赋值给statement变量,以便后续使用该对象执行查询或更新操作。
(2)注意处理异常,用try/catch 即可
(3)PreparedStatement statement = null;定义的时候注意位置,不要写在try循环中了,应该让statement变量的生命周期为整个SQLException类

3.执行SQL语句

ResultSet resultSet = null;
resultSet = statement.executeQuery();

执行一个SQL查询语句,并将查询结果存储在resultSet对象中。

(1)statement是一个java.sql.Statement对象,通过调用executeQuery()方法,可以执行该语句并返回一个java.sql.ResultSet对象,该对象包含了查询结果的数据。
(2)executeQuery()方法是Statement接口的一个方法,用于执行SQL查询语句并返回一个ResultSet对象。这个方法可以执行不同类型的查询语句,如SELECT、UPDATE、INSERT和DELETE等。
(3)resultSet是一个java.sql.ResultSet对象,它表示了查询结果的数据集合。通过执行查询语句后,将查询结果填充到resultSet对象中,可以通过遍历resultSet来获取每一行的数据。

ResultSet resultSet = null;定义的时候注意位置,不要写在try循环中了,应该让resultSet 变量的生命周期为整个SQLException类

4.处理结果集

List<Image> images = new ArrayList<>();//查找所有的结果返回不止一条数据,所以用列表存放结果集
            while (resultSet.next()){
                Image image = new Image();
                image.setImageId(resultSet.getInt("imageID"));
                image.setImageName(resultSet.getString("imageName"));
                image.setSize(resultSet.getInt("size"));
                image.setUploadTime(resultSet.getString("uploadTime"));
                image.setContentType(resultSet.getString("contentType"));
                image.setPath(resultSet.getString("path"));
                image.setMd5(resultSet.getString("Md5"));
                images.add(image);
            }
            return images;

while (resultSet.next()){
resultSet.next()是ResultSet接口的一个方法,用于将游标移动到下一行数据。当存在下一行数据时,该方法返回true;当没有更多行数据时,返回false。返回值为true即有下一行数据时继续执行,返回值为false时,光标无法下移一行时说明结果集遍历结束,跳出循环。
List<Image> images = new ArrayList<>();定义的时候注意位置,不要写在try循环中了,应该让images 变量的生命周期为整个SQLException类
image.setImageId(resultSet.getInt("imageID"));从数据库查询结果集(resultSet)中提取图像ID,并将其赋值给image对象的图像ID属性
image.setImageName(resultSet.getString("imageName"));使用resultSet.getString(“imageName”)获取结果集中的字符串值,并将其设置为image对象的图像名称。

5.关闭数据库链接

DBUtil.close(connection,statement, resultSet);

仍旧用finally 将其包裹来保证关闭连接的这行代码一定会执行

6.查找所有图片属性完整代码

    //查找数据库全部图片信息,查找全部
    public List<Image> selectAll()throws SQLException {
        /*
        1.与数据库建立链接  Connection connection = DBUtil.getConnection();
        2.创建并拼接SQL语句   String SQL= " ";   PreparedStatement statement = connection.prepareStatement(SQL);
        3.执行SQL语句
        4.处理结果集
        5.断开连接
        存放结果集:
         */
        List<Image> images = new ArrayList<>();//查找所有的结果返回不止一条数据,所以用列表存放结果集
        Connection connection = DBUtil.getConnection();//建立数据库连接
        String SQL = "select *from image;";//构造SQL语言
        PreparedStatement statement = null;//statement 用于拼接SQL语言
        ResultSet resultSet = null;
        try{
            statement = connection.prepareStatement(SQL);//拼接SQL语言
            //执行SQL
            resultSet = statement.executeQuery();
            while (resultSet.next()){
                Image image = new Image();
                image.setImageId(resultSet.getInt("imageID"));
                image.setImageName(resultSet.getString("imageName"));
                image.setSize(resultSet.getInt("size"));
                image.setUploadTime(resultSet.getString("uploadTime"));
                image.setContentType(resultSet.getString("contentType"));
                image.setPath(resultSet.getString("path"));
                image.setMd5(resultSet.getString("Md5"));
                images.add(image);
            }
            return images;

        }catch (SQLException e){
            e.printStackTrace();
        }finally {
            DBUtil.close(connection,statement, resultSet);
        }

        return null;

    }

三、按照图片Id查找某一图片属性

1.与数据库建立连接

Connection connection = DBUtil.getConnection();

2.创建并拼接SQL语句

String SQL= "delete from image where imageId = ?";
PreparedStatement statement = null;
statement = connection.prepareStatement(SQL);

PreparedStatement statement = connection.prepareStatement(SQL);

创建statemment对象来储存:SQL语句进行预编译后转换为一个可执行的PreparedStatement对象的结果

PreparedStatement statement = null;注意statement对象的生命周期,最好创建在try外面

3.执行SQL语句

ResultSet resultSet = null;
statement.setInt(1,imageId);
ResultSet resultSet = null;
resultSet = statement.executeQuery();

ResultSet resultSet = null;:定义resultSet对象,让其先为空,注意resultSet的生命周期
statement.setInt(1,imageId);

将int类型的imageId参数的数值传入statement中的第一个占位符处(imageId在构造方法时便定义了,数值在掉用该方法时传入)

resultSet = statement.executeQuery();

通过调用 statement.executeQuery();执行statement中预编译后的SQL语句,并将结果返回给resultSet,后续可以使用resultSet对象来处理查询结果

4.处理结果集

            if (resultSet.next()) {
                Image image = new Image();
                image.setImageId(resultSet.getInt("imageID"));
                image.setImageName(resultSet.getString("imageName"));
                image.setSize(resultSet.getInt("size"));
                image.setUploadTime(resultSet.getString("uploadTime"));
                image.setContentType(resultSet.getString("contentType"));
                image.setPath(resultSet.getString("path"));
                image.setMd5(resultSet.getString("Md5"));
                return image;
            }

(1) if (resultSet.next()){

resultSet.next()是ResultSet接口的一个方法,用于将游标移动到下一行数据。当存在下一行数据时,该方法返回true;当没有更多行数据时,返回false。返回值为true即有下一行数据时继续执行,返回值为false时,光标无法下移一行时说明结果集遍历完成,因为此处是查找一条数据,结果集中也只有一条数据,不需要while循环

(2)image.setImageId(resultSet.getInt("imageID"));

从数据库查询结果集(resultSet)中提取图像ID,并将其赋值给image对象的图像ID属性

(3) image.setImageName(resultSet.getString("imageName"));

使用resultSet.getString(“imageName”)获取结果集中的字符串值,并将其设置为image对象的图像名称。

5.关闭数据库链接

DBUtil.close(connection,statement,resultSet);

仍旧用finally 将其包裹来保证关闭连接的这行代码一定会执行

6.按照ID查找图片属性完整代码

    //查找数据库中的图片,按照imageID查找
    public Image selectOneId(int imageId) throws SQLException{
        /*
        1.与数据库建立链接  Connection connection = DBUtil.getConnection();
        2.创建并拼接SQL语句   String SQL= " ";   PreparedStatement statement = connection.prepareStatement(SQL);
        3.执行SQL语句
        4.处理结果集
        5.断开连接
         */
        Connection connection = DBUtil.getConnection();
        String SQL= "select * from image where imageId = ?";
        PreparedStatement statement = null;
        ResultSet resultSet = null;
        try {
            statement = connection.prepareStatement(SQL);
            statement.setInt(1,imageId);
            resultSet = statement.executeQuery();
            if (resultSet.next()) {
                Image image = new Image();
                image.setImageId(resultSet.getInt("imageID"));
                image.setImageName(resultSet.getString("imageName"));
                image.setSize(resultSet.getInt("size"));
                image.setUploadTime(resultSet.getString("uploadTime"));
                image.setContentType(resultSet.getString("contentType"));
                image.setPath(resultSet.getString("path"));
                image.setMd5(resultSet.getString("Md5"));
                return image;

            }
        }catch (SQLException e){
            e.printStackTrace();
        }finally {
            DBUtil.close(connection,statement,resultSet);
        }

        return null;
    }

7.按照ID查找图片和查找全部图片的区别

不同点:

(1)方法返回值不同()

查找所有图片返回值为List<Image>
查找全部图片因为图片不止一组Image所以要用 List<Image> 的返回值,并且在方法中定义List<Image>存储结果

按照ID查找图片返回值为Image
查找全部图片因为图片只有一组Image所以要用 Image的返回值,并且在方法中定义Image存储结果

(2)方法的传入参数不同

查找全部图片信息没有传入参数

按照ID查找图片有传入参数imageId
在构造SQL语言时有一位占位符:String SQL= "select * from image where imageId = ?";
所以需要读取传入的imageId值给该占位符:statement.setInt(1,imageId);

(3)处理结果集时

查找全部图片信息处理结果集使用while循环
因为查找全部图片结果集中不止一组数据,所以需要用到循环

按照ID查找图片处理结果集使用if判断
在按照ID查找图片时最多只会查到一组image数据

相同点:

(1)都有处理结果集的这一步骤,

处理结果集步骤基本相同,只有使用while循环或if判断上存在区别

(2)基本步骤都是相同的(基本所有的对数据库操作步骤都是如此):

a.建立数据库连接 Connection connection = DBUtil.getConnection();
b.执行SQL语句String SQL= " "; PreparedStatement statement = connection.prepareStatement(SQL);
c.执行SQL语句 ResultSet resultSet = statement.executeQuery(); 或者int ret = statement.executeUpdate();(删除或是新增操作时)
d.断开连接 DBUtil.close(connection,statement, resultSet);用finally保证断开连接一定会被执行(close中参数根据具体情况写)


四、删除某一图片(按照图片Id)

1.与数据库建立连接

Connection connection = DBUtil.getConnection();

2.创建并拼接SQL语句

String SQL= "delete from image where imageId = ?";
PreparedStatement statement = null;
statement = connection.prepareStatement(SQL);

PreparedStatement statement = connection.prepareStatement(SQL);创建statemment对象来储存:SQL语句进行预编译后转换为一个可执行的PreparedStatement对象的结果

3.执行SQL语句

        statement.setInt(1,imageId);
        int ret = statement.executeUpdate();
        if (ret != 1) {
            //ret不等于1说明SQL没有执行,删除操作失败
            throw new JavaImageServerException("删除图片信息出错");
        }

statement.setInt(1,imageId);

将int类型的imageId参数的数值传入statement中的第一个占位符处(imageId在构造方法时便定义了,数值在掉用该方法时传入)

int ret = statement.executeUpdate();

执行SQL语句,并返回一个整数表示这次SQL执行时受影响的行数

if (ret != 1)

如果ret也就是SQL语句执行时受影响行数不等于1,即数据库中受影响行数不为1时,说明删除操作失败, 因为我们这里进行的是按照ID删除数据,每次删除操作只会影响到数据库中的一条数据,所以受影响行数应该为1

throw new JavaImageServerException("删除图片信息出错");

删除图片失败我们应该返回一个异常,用之前定义过的 JavaImageServerException 类

4.关闭数据库链接

 DBUtil.close(connection,statement,null);

5.按照ID删除一张图片属性完整代码

    public void deleteOneId(int imageId) throws SQLException, JavaImageServerException {
        /*
        1.与数据库建立链接  Connection connection = DBUtil.getConnection();
        2.创建并拼接SQL语句   String SQL= " ";   PreparedStatement statement = connection.prepareStatement(SQL);
        3.执行SQL语句
        4.断开连接
         */
        Connection connection = DBUtil.getConnection();
        String SQL= "delete from image where imageId = ?";
        PreparedStatement statement = null;
        statement = connection.prepareStatement(SQL);
        statement.setInt(1,imageId);
        int ret = statement.executeUpdate();
        if (ret != 1) {
            //ret不等于1说明SQL没有执行,删除操作失败
            throw new JavaImageServerException("删除图片信息出错");
        }
        DBUtil.close(connection,statement,null);

    }


五、完整ImageDao类代码

package dao;

import com.mysql.cj.jdbc.MysqlDataSource;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.concurrent.SynchronousQueue;

public class DBUtil {
    //获取数据库连接
    private static final String URL = "jdbc:mysql://127.0.0.1:3306/image_table?characterEncoding=utf8&useSSL=false&serverTimezone=UTC&allowPublicKeyRetrieval=true";
    private static final String USERNAME = "root";
    private static final String PASSWORD = "123456";
    private static volatile DataSource dataSource = null;
    //定义了一个私有的、静态的、易变的DataSource类型的变量,并且将其初始化为null

    public static DataSource getDataSource(){
        //懒汉模式,在
        if(dataSource == null){
            Synchronized(DBUtil.class);{
                if(dataSource == null){
                    //dataSource 变量被初始化为一个新的 MysqlDataSource 对象,
                    // 在方法开始时,如果 dataSource 已经被赋值为其他对象,则会保留其原始值,而不会再次创建新的数据源对象。
                    dataSource = new MysqlDataSource();

                    // 将 dataSource 强制转换为 MysqlDataSource 类型,并将结果赋值给名为 tmpDataSour 的变量。
                    // 并使用 setURL()、setUser() 和 setPassword() 方法设置数据库连接的相关信息,包括 URL、用户名和密码。
                    MysqlDataSource tmpDataSour = (MysqlDataSource) dataSource;
                    tmpDataSour.setURL(URL);
                    tmpDataSour.setUser(USERNAME);
                    tmpDataSour.setPassword(PASSWORD);
                }
            }

        }

        return dataSource;
    }
    //建立连接
    public static Connection getConnection() throws SQLException {
        //从一个数据源(DataSource)对象中获取数据库连接,以便执行SQL语句和操作数据库。
        // 数据源可以是配置文件中定义的数据源,也可以是通过编程方式创建的数据源
        return getDataSource().getConnection();

    }
    //关闭连接
    public static void close(Connection connection, PreparedStatement preparedStatement, ResultSet resultSet) throws RuntimeException {
        //connection(数据库连接对象)、preparedStatement(预处理语句对象)和、resultSet(结果集对象)
        //关闭链接顺序必须是先建立后关闭


        //(1)检查 resultSet(结果集对象)是否为非空,如果是,则尝试关闭结果集。
        // 如果关闭过程中发生 SQLException 异常,将抛出一个运行时异常。
        if(resultSet != null) {
            try {
                resultSet.close();
            } catch (SQLException e) {
                throw new RuntimeException(e);
            }
        }

        //(2)它检查 preparedStatement(预处理语句对象)是否为非空,如果是,则尝试关闭预处理语句。
        // 如果关闭过程中发生 SQLException 异常,将抛出一个运行时异常。
        if(preparedStatement != null){
            try {
                preparedStatement.close();
            } catch (SQLException e) {
                throw new RuntimeException(e);
            }
        }

        //(3)它检查 connection(数据库连接对象)是否为非空,如果是,则尝试关闭数据库连接。
        // 如果关闭过程中发生 SQLException 异常,将抛出一个运行时异常。
        if (connection != null){
            try {
                connection.close();
            } catch (SQLException e) {
                throw new RuntimeException(e);
            }
        }
        }
    private static void Synchronized(Class<DBUtil> dbUtilClass) {
    }
}

六、图片服务器其他文章链接

1.图片服务器的设计(数据库设计&前后端交互API设计):大饼的图片服务器01

2.图片服务器建立JDBC连接(pom.xml & Image类 & DBUtil类):大饼的图片服务器2


感谢您对大饼的支持,今天的你也很努力呦

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值