ImageDao详解
- 一、向数据库中写入图片属性
- 1.与数据库建立连接
- 2.创建并拼接SQL语句
- 3.执行SQL语句
- 4.定义异常类JavaImageServerException
- 5.关闭数据库连接
- 6.写入图片的完整代码
- 二、查找数据库中所有图片属性
- 1.与数据库建立连接
- 2.创建并拼接SQL语句
- 3.执行SQL语句
- 4.处理结果集
- 5.关闭数据库链接
- 6.查找所有图片属性完整代码
- 三、按照图片Id查找某一图片属性
- 1.与数据库建立连接
- 2.创建并拼接SQL语句
- 3.执行SQL语句
- 4.处理结果集
- 5.关闭数据库链接
- 6.按照ID查找图片属性完整代码
- 7.按照ID查找图片和查找全部图片的区别
- 四、删除某一图片(按照图片Id)
- 1.与数据库建立连接
- 2.创建并拼接SQL语句
- 3.执行SQL语句
- 4.关闭数据库链接
- 5.按照ID删除一张图片属性完整代码
- 五、完整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