PreparedStatement实现对表数据的增删改查操作-详解

3 篇文章 0 订阅

PreparedStatement的使用的插入案例进行封装如下

JDBCUtils.java

package com.atmf;

import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.util.Properties;

import org.junit.Test;

public class JDBCUtils {
	/**
	 * @Describe 获取数据库的连接
	 * @auther mofei
	 * @date 2020年11月3日下午6:25:54
	 */
	public static Connection getConnection() throws Exception{
		//1,加载配置文件
		InputStream is = ClassLoader.getSystemClassLoader().getResourceAsStream("jdbc.properties");
		Properties pr = new Properties();
		pr.load(is);
		
		//2,读取配置信息
		String user = pr.getProperty("user");
		String password = pr.getProperty("password");
		String url = pr.getProperty("url");
		String driverClass = pr.getProperty("driverClass");
		
		//3.加载驱动
		Class.forName(driverClass);
		
		//4,获取连接
		Connection con = DriverManager.getConnection(url, user,password);
		return con;
	}

	//增删改资源的关闭
	public static void closeReource(Connection con, PreparedStatement ps){
		try {
			if(ps != null)
				ps.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
		try {
			if(con != null)
				con.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	//查询资源的关闭
	public static void closeResource(java.sql.Connection con, PreparedStatement ps, ResultSet rs){
		try {
			if(con != null)
				con.close();
		} catch (SQLException e) {
			e.printStackTrace();
		}
		try {
			if(ps != null)
				ps.close();
		} catch (SQLException e) {
			e.printStackTrace();
		}
		try {
			if(rs != null)
				rs.close();
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}	
}

对表进行增删改操作


修改

package com.atmf;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;

import org.junit.Test;

public class PreparedStatementUpdateTest {
	@Test
	public void testUpdate() {		
		Connection con = null;
		PreparedStatement ps = null;
		try {
			//1,获取数据库的连接
			con = JDBCUtils.getConnection();
			//2,预编译sql语句,返回PreparedStatement的实例
			String sql = "update customers set name = ? where id = ?";
			ps = con.prepareStatement(sql);
			//3,填充占位符
			ps.setObject(1, "提莫");
			ps.setObject(2, 1);
			//4,执行
			ps.execute();
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {
			//5,资源的关闭
			JDBCUtils.closeReource(con, ps);
		}
	}
}

结果:
修改前
修改后


插入

package com.atmf;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;

import org.junit.Test;

public class PreparedStatementUpdateTest {
	@Test
	public void testUpdate() {		
		Connection con = null;
		PreparedStatement ps = null;
		try {
			//1,获取数据库的连接
			con = JDBCUtils.getConnection();
			//2,预编译sql语句,返回PreparedStatement的实例
			String sql = "insert into customers(name) value(?)";
			ps = con.prepareStatement(sql);
			//3,填充占位符
			ps.setObject(1, "王者农药");
			SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
			Date date = sdf.parse("1995-11-03");
			ps.setDate(2, new java.sql.Date(date.getTime()));
			//4,执行
			ps.execute();
		} catch (SQLException e) {
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			//5,资源的关闭
			JDBCUtils.closeReource(con, ps);
		}
	}
}

在这里插入图片描述


删除

package com.atmf;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;

import org.junit.Test;

public class PreparedStatementUpdateTest {
	@Test
	public void testUpdate() {		
		Connection con = null;
		PreparedStatement ps = null;
		try {
			//1,获取数据库的连接
			con = JDBCUtils.getConnection();
			//2,预编译sql语句,返回PreparedStatement的实例
			String sql = "delete from customers where id = ?";
			ps = con.prepareStatement(sql);
			//3,填充占位符
			ps.setObject(1, 3);
			//4,执行
			ps.execute();
		} catch (SQLException e) {
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			//5,资源的关闭
			JDBCUtils.closeReource(con, ps);
		}
	}
}

在这里插入图片描述


以上,对表的增删改操作之间的不同就是SQL语句的不同,将其进行封装从而实现对同一数据库中表的增删改操作的通用,通过调用update()方法就能完成,代码如下所示。


通用的增删改操作

	public void update(String sql, Object ...args) {
		Connection con =null;
		PreparedStatement ps = null;
		try {
			//1,获取数据库的连接
			con = JDBCUtils.getConnection();
			//2,预编译sql语句,返回PreparedStatement的实例
			ps = con.prepareStatement(sql);
			//3,填充占位符
			for(int i = 0; i < args.length; i++) {
				ps.setObject(i + 1, args[i]);
			}
			//4,执行
			ps.execute();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			//5,资源的关闭
			JDBCUtils.closeReource(con, ps);
		}		
	}

对表进行查询操作

                     ORM编程思想
  对象关系映射(英语:Object Relational Mapping,简称ORM,或O/RM,或O/R mapping),是一种程序设计技术,用于实现面向对象编程语言里不同类型系统的数据之间的转换。从效果上说,它其实是创建了一个可在编程语言里使用的“虚拟对象数据库”。
  对象数据库是一种以对象形式表示信息的数据库。对象数据库的数据库管理系统被称为ODBMS或OODBMS。
  两个主要原因让用户使用对象数据库技术。首先,关系数据库在管理复杂数据时显得笨重。其次,被应用软件操作的数据一般是用面向对象的编程语言如C++,Java,Delphi和C#写成,而那些用来转化数据表示和关系数据库元组的代码很冗繁,执行时也有不少耗时。这种应用程序和数据库表示信息的模式之间的不匹配有时也被称为impedance mismatch。
  简单来讲:一个数据表对应一个java类,表中的一条记录对应java类的一个对象,表中的一个字段对应java类的一个属性

Java与SQL对应数据类型转换表
Java类型SQL类型
booleanBIT
byteTINYINT
shortSMALLINT
intINTEGER
longBIGINT
StringCHAR,VARCHAR,LONGVARCHAR
byte arrayBINARY , VAR BINARY
java.sql.DateDATE
java.sql.TimeTIME
java.sql.TimestampTIMESTAMP

ResultSetMetaData
  • 可用于获取关于 ResultSet 对象中列的类型和属性信息的对象

  • ResultSetMetaData rsmd = rs.getMetaData();

    • getColumnName(int column):获取指定列的名称

    • getColumnLabel(int column):获取指定列的别名

    • getColumnCount():返回当前 ResultSet 对象中的列数。

    • getColumnTypeName(int column):检索指定列的数据库特定的类型名称。

    • getColumnDisplaySize(int column):指示指定列的最大标准宽度,以字符为单位。

    • isNullable(int column):指示指定列中的值是否可以为 null。

    • isAutoIncrement(int column):指示是否自动为指定列进行编号,这样这些列仍然是只读的。


第一个查询操作

第一步:建立数据库及表

CREATE DATABASE test;
USE test;
CREATE TABLE customers(
	`id` INT(10) NOT NULL AUTO_INCREMENT PRIMARY KEY,
	`name` VARCHAR(15) DEFAULT NULL,
	`email` VARCHAR(20) DEFAULT NULL,
	`birth` DATE DEFAULT NULL,
	`photo` MEDIUMBLOB DEFAULT NULL
);
INSERT INTO customers(`name`,`email`,`birth`) 
VALUES('君莫笑','yege@qzgs.com','2035-05-29'),
('苏沐橙','mucheng@)qzgs.com','2042-02-18'),
('黄少天','hualao@qzgs.com','2038-06-12');

第二步:创建一个数据库对象映射的java类

public class Customer {
    private int id;
    private String name;
    private String email;
    private Date birth;

    public Customer() {
    }

    public Customer(int id, String name, String email, Date birth) {
        this.id = id;
        this.name = name;
        this.email = email;
        this.birth = birth;
    }

    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 String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public Date getBirth() {
        return birth;
    }

    public void setBirth(Date birth) {
        this.birth = birth;
    }

    @Override
    public String toString() {
        return "Customer{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", email='" + email + '\'' +
                ", birth=" + birth +
                '}';
    }
}

第三步:创建配置文件

user=root
password=123456
url=jdbc:mysql://localhost:3306/test
driverClass=com.mysql.jdbc.Driver

第四步:案例测试

    @Test
    public void queryTest() {
        Connection conn = null;
        PreparedStatement ps = null;
        ResultSet rs = null;
        try {
            //建立连接
            conn = JDBCUtils.getConnection();
            //预编译sql语句
            String sql = "select id,name,email,birth from customers where id = ?";
            ps = conn.prepareStatement(sql);
            //填充占位符
            ps.setInt(1,1);
            //执行,并返回结果集
            rs = ps.executeQuery();
            //处理结果集
            if(rs.next()){
                //获取当前这条数据的各个字段值
                int id = rs.getInt(1);
                String name = rs.getString(2);
                String email = rs.getString(3);
                Date birth = rs.getDate(4);

                System.out.println(new Customer(id,name,email,birth));
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            //关闭资源(关闭conn连接,ps,rs)
//        ps.close();//立即释放这个语句对象的数据库和JDBC资源,而不是等待它自动关闭时发生。通常好的做法是在使用完资源后立即释放它们,以避免占用数据库资源。
//        conn.close();//立即释放这个连接对象的数据库和JDBC资源,而不是等待它们被自动释放
//        rs.close();//立即释放这个ResultSet对象的数据库和JDBC资源,而不是在自动关闭时等待该操作发生。
            //将上面的是三个关闭资源写入JDBCUtils.java文件(本篇开头那个文件)中直接调用
            JDBCUtils.closeResource(conn,ps,rs);
        }
    }

第五步:控制台打印结果显示

Customer{id=1, name='君莫笑', email='yege@qzgs.com', birth=2035-05-29}

-------------------------------------------------------------------------------------------------------------------------

涉及到 ResultSet()—>结果集ResultSetMetaData()—>结果集元数据反射

针对于各自的表的通用查询

通用的查询操作1

常用的方法:

ResultSet
  • 查询需要调用PreparedStatement 的 executeQuery() 方法,查询结果是一个ResultSet 对象

  • ResultSet 对象以逻辑表格的形式封装了执行数据库操作的结果集,ResultSet 接口由数据库厂商提供实现

  • ResultSet 返回的实际上就是一张数据表。有一个指针指向数据表的第一条记录的前面。

  • ResultSet 对象维护了一个指向当前数据行的游标,初始的时候,游标在第一行之前,可以通过 ResultSet 对象的 next() 方法移动到下一行。调用 next()方法检测下一行是否有效。若有效,该方法返回 true,且指针下移。相当于Iterator对象的 hasNext() 和 next() 方法的结合体。

  • 当指针指向一行时, 可以通过调用 getXxx(int index) 或 getXxx(int columnName) 获取每一列的值。

    • 例如: getInt(1), getString(“name”)
    • 注意:Java与数据库交互涉及到的相关Java API中的索引都从1开始。

Object getObject(int columnIndex) throws SQLException;


用到的方法:

ResultSetMetaData
  • 可用于获取关于 ResultSet 对象中列的类型和属性信息的对象

  • ResultSetMetaData rsmd = rs.getMetaData();

    • getColumnName(int column):获取指定列的名称

    • getColumnLabel(int column):获取指定列的别名

    • getColumnCount():返回当前 ResultSet 对象中的列数。

    • getColumnTypeName(int column):检索指定列的数据库特定的类型名称。

    • getColumnDisplaySize(int column):指示指定列的最大标准宽度,以字符为单位。

    • isNullable(int column):指示指定列中的值是否可以为 null。

    • isAutoIncrement(int column):指示是否自动为指定列进行编号,这样这些列仍然是只读的。


在这里插入图片描述

    //通用查询操作
    public Customer queryForCustomers(String sql,Object ...args) {
        Connection conn = null;
        PreparedStatement ps = null;
        ResultSet rs = null;
        try {
            //第一步:获取连接
            conn = JDBCUtils.getConnection();
            //第二步:预编译sql语句 将查询语句手动输入,args表示可变的占位符参数
            ps = conn.prepareStatement(sql);
            //第三步:填充占位符
            for(int i = 0;i < args.length;i++){
                ps.setObject(i + 1,args[i]);//占位符参数索引是从1开始的
            }
            //第四步:执行,并返回结果集
            rs = ps.executeQuery();
            //第五步:处理结果集
            //如果有数据,就去取数据,但是取几次呢???这就需要结果集元数据(ResultSetMetaData getMetaData():检索此ResultSet对象的列的数量、类型和属性。)
            ResultSetMetaData rsmd = rs.getMetaData();
            //获取结果集的列数
            int columnCount = rsmd.getColumnCount();
            if(rs.next()){
                Customer customer = new Customer();
                //处理结果集一行数据中的每一个列
                for(int i = 0;i < columnCount;i++){
                    //获得结果集上的列值
                    Object columnValue = rs.getObject(i + 1);
                    //获得值对应的列名字段
                    String columnName = rsmd.getColumnName(i + 1);
                    //通过反射给customer对象指定的columnClassName属性,赋值为columnValue
                    Field field = Customer.class.getDeclaredField(columnName);
                    field.setAccessible(true);
                    field.set(customer,columnValue);//第一个参数:要传入设置的对象,第二个参数:要传入实参
                }
                return customer;
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            //第六步:关闭资源
            JDBCUtils.closeResource(conn,ps,rs);
        }
        //如果没有结果,返回null
        return null;
    }

测试:

    @Test
    public void queryForCustomersTest(){
        String sql = "select id,name,birth,email from customers where id = ?";
        Customer customer = queryForCustomers(sql, 2);
        System.out.println(customer);
    }

结果打印:

Customer{id=2, name='苏沐橙', email='mucheng@)qzgs.com', birth=2042-02-18}

通用的查询操作2

说明通用查询操作2与通用查询操作1就只有2行代码不同
1,sql字符串的书写不同
2,将获取每个列的列名:getColumnName() ———替换为————>获取每个列的别名:getColumnLabel()
3,在数据库字段名与java中属性名一致情况下,可以使用getColumnName(),反之,则会报错:没有这个字段
4,如果sql中没有给字段中起别名,getColumnLabel()获取的就是别名,所以不管有没有写别名都可以使用用getColumnLabel(尽量使用getColumnLabel)

将数据库test中customers表的字段名更改一下,以致表字段名与数据库对象映射的java类中的属性名不一致,或者另外创建一个表acg,表结构如下:

CREATE TABLE acg(
	id INT(10) NOT NULL AUTO_INCREMENT PRIMARY KEY,
	`acg_name` VARCHAR(15) DEFAULT NULL,
	`acg_email` VARCHAR(20) DEFAULT NULL,
	`acg_birth` DATE DEFAULT NULL,
	`acg_photo` MEDIUMBLOB DEFAULT NULL
);
INSERT INTO acg(`acg_name`,`acg_email`,`acg_birth`) 
VALUES('君莫笑','yege@qzgs.com','2035-05-29'),
('苏沐橙','mucheng@)qzgs.com','2042-02-18'),
('黄少天','hualao@qzgs.com','2038-06-12');

同时数据库对象映射的java类中的属性名也要更改,使用驼峰命名法:

public class Acg {
    private int acgId;
    private String acgName;
    private String acgEmail;
    private Date acgBirth;
    ...

其余保持不变。进行测试:

    public Acg queryForCustomers2(String sql,Object ...args) {
        Connection conn = null;
        PreparedStatement ps = null;
        ResultSet rs = null;
        try {
            //获得连接
            conn = JDBCUtils.getConnection();
            //预编译sql语句
            ps = conn.prepareStatement(sql);
            //填充占位符
            for(int i = 0;i < args.length;i++){
                ps.setObject(i + 1,args[i]);
            }
            //执行,并返回结果集
            rs = ps.executeQuery();
            //获得结果集元数据
            ResultSetMetaData rsmd = rs.getMetaData();
            //获得结果集元数据的列数
            int columnCount = rsmd.getColumnCount();
            if(rs.next()){
                Acg acg = new Acg();
                for(int i = 0;i < columnCount;i++){
                    Object columnValue = rs.getObject(i + 1);
                    String columnLabel = rsmd.getColumnLabel(i + 1);

                    //通过反射给customer对象指定的columnClassName属性,赋值为columnValue
                    Field field = Acg.class.getDeclaredField(columnLabel);
                    field.setAccessible(true);
                    field.set(acg,columnValue);
                }
                return acg;
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            //关闭资源
            JDBCUtils.closeResource(conn,ps,rs);
        }
        return null;
    }

测试:

    @Test
    public void queryForCustomersTest2() {
        String sql = "select acg_id acgId,acg_name acgName,acg_email acgEmail,acg_birth acgBirth from acg where acg_id = ?";
        Acg acg = queryForCustomers2(sql, 3);
        System.out.println(acg);
    }

结果打印:

Acg{acgId=3, acgName='黄少天', acgEmail='hualao@qzgs.com', acgBirth=2038-06-12}

-------------------------------------------------------------------------------------------------------------------------

针对于通用的表的通用查询

通用的表的查询操作,用于返回数据表中的一条记录

使用泛型方法

public class PreparedStatementTest {
    public <T> T queryForTable(Class<T> clazz,String sql,Object ...args){
        Connection conn = null;
        PreparedStatement ps = null;
        ResultSet rs = null;
        try {
            //获得连接
            conn = JDBCUtils.getConnection();
            //预编译sql语句
            ps = conn.prepareStatement(sql);
            //填充占位符
            for(int i = 0;i < args.length;i++){
                ps.setObject(i + 1,args[i]);
            }
            //执行,并返回结果集
            rs = ps.executeQuery();
            //获得结果集元数据
            ResultSetMetaData rsmd = rs.getMetaData();
            //获得结果集元数据的列数
            int columnCount = rsmd.getColumnCount();
            if(rs.next()){
                T t = clazz.newInstance();
                for(int i = 0;i < columnCount;i++){
                    Object columnValue = rs.getObject(i + 1);
                    String columnLabel = rsmd.getColumnLabel(i + 1);

                    //通过反射给customer对象指定的columnClassName属性,赋值为columnValue
                    Field field = clazz.getDeclaredField(columnLabel);
                    field.setAccessible(true);
                    field.set(t,columnValue);
                }
                return t;
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            //关闭资源
            JDBCUtils.closeResource(conn,ps,rs);
        }
        return null;
    }
    @Test
    public void queryForTableTest(){
        String sql1 = "select id,name,birth,email from customers where id = ?";
        Customer customer = queryForTable(Customer.class,sql1, 1);
        System.out.println(customer);

        String sql2 = "select acg_id acgId,acg_name acgName,acg_email acgEmail,acg_birth acgBirth from acg where acg_id = ?";
        Acg acg = queryForTable(Acg.class,sql2, 2);
        System.out.println(acg);
    }
}

测试结果:

Customer{id=1, name='君莫笑', email='yege@qzgs.com', birth=2035-05-29}
Acg{acgId=2, acgName='苏沐橙', acgEmail='mucheng@)qzgs.com', acgBirth=2042-02-18}

通用的表的查询操作,用于返回数据表中的多条记录

public class PreparedStatementTest {
    public <T> List<T> queryForList(Class<T> clazz, String sql, Object ...args){
        Connection conn = null;
        PreparedStatement ps = null;
        ResultSet rs = null;
        try {
            //获得连接
            conn = JDBCUtils.getConnection();
            //预编译sql语句
            ps = conn.prepareStatement(sql);
            //填充占位符
            for(int i = 0;i < args.length;i++){
                ps.setObject(i + 1,args[i]);
            }
            //执行,并返回结果集
            rs = ps.executeQuery();
            //获得结果集元数据
            ResultSetMetaData rsmd = rs.getMetaData();
            //获得结果集元数据的列数
            int columnCount = rsmd.getColumnCount();
            //创建一个集合,用于存储对象
            ArrayList<T> list = new ArrayList<>();
            while(rs.next()){
                T t = clazz.newInstance();
                for(int i = 0;i < columnCount;i++){
                    Object columnValue = rs.getObject(i + 1);
                    String columnLabel = rsmd.getColumnLabel(i + 1);

                    //通过反射给customer对象指定的columnClassName属性,赋值为columnValue
                    Field field = clazz.getDeclaredField(columnLabel);
                    field.setAccessible(true);
                    field.set(t,columnValue);
                }
                list.add(t);
            }
            return list;
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            //关闭资源
            JDBCUtils.closeResource(conn,ps,rs);
        }
        return null;
    }
    @Test
    public void queryForListTest(){
        String sql2 = "select acg_id acgId,acg_name acgName,acg_email acgEmail,acg_birth acgBirth from acg where acg_id < ?";
        List<Acg> list = queryForList(Acg.class, sql2, 4);
        for(Acg acg : list){
            System.out.println(acg);
        }
    }
}

测试结果:

Acg{acgId=1, acgName='君莫笑', acgEmail='yege@qzgs.com', acgBirth=2035-05-29}
Acg{acgId=2, acgName='苏沐橙', acgEmail='mucheng@)qzgs.com', acgBirth=2042-02-18}
Acg{acgId=3, acgName='黄少天', acgEmail='hualao@qzgs.com', acgBirth=2038-06-12}

操作BLOB类型字段

MySQL BLOB类型

  • MySQL中,BLOB是一个二进制大型对象,是一个可以存储大量数据的容器,它能容纳不同大小的数据。
  • 插入BLOB类型的数据必须使用PreparedStatement,因为BLOB类型的数据无法使用字符串拼接写的。
  • MySQL的四种BLOB类型(除了在存储的最大信息量上不同外,他们是等同的)

MySQL有四种BLOB类型:
  tinyblob:仅255个字符
  blob:最大限制到65K字节
  mediumblob:限制到16M字节
  longblob:可达4GB

  • 实际使用中根据需要存入的数据大小定义不同的BLOB类型。
  • 需要注意的是:如果存储的文件过大,数据库的性能会下降。
  • 如果在指定了相关的Blob类型以后,还报错:xxx too large,那么在mysql的安装目录下,找my.ini文件加上如下的配置参数: max_allowed_packet=16M。同时注意:修改了my.ini文件之后,需要重新启动mysql服务。

向数据表acg插入Blob类型的数据
public class BlobTest {
    @Test
    public void insertBlobTest() {
        Connection conn = null;
        PreparedStatement ps = null;
        try {
            conn = JDBCUtils.getConnection();
            String sql = "insert into acg(`acg_name`,`acg_email`,`acg_birth`,`acg_photo`) values(?,?,?,?)";
            ps = conn.prepareStatement(sql);
            ps.setObject(1,"叶修");
            ps.setObject(2,"yebuxiu@qzgs.com");
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            Date date = sdf.parse("2035-05-29");
            ps.setObject(3,date);
            FileInputStream fis = new FileInputStream(new File("src\\叶修.gif"));
            ps.setObject(4,fis);
            ps.execute();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            JDBCUtils.closeResource(conn,ps);
        }
    }
}

在这里插入图片描述

执行结果:(找了个动图,它不会不动,hh)
在这里插入图片描述

将Blob类型字段的数据,下载下来保存到本地
public class BlobTest {
    @Test
    public void queryBlobTest() {
        Connection conn = null;
        PreparedStatement ps = null;
        ResultSet rs = null;
        InputStream is = null;
        FileOutputStream fos = null;
        try {
            conn = JDBCUtils.getConnection();
            String sql = "select `acg_id`,`acg_name`,`acg_email`,`acg_birth`,`acg_photo` from acg where `acg_id` = ?";
            ps = conn.prepareStatement(sql);
            ps.setInt(1,4);

            rs = ps.executeQuery();
            if(rs.next()){
                int acgId = rs.getInt("acg_id");
                String acgName = rs.getString("acg_name");
                String acgEmail = rs.getString("acg_email");
                Date acgBirth = rs.getDate("acg_birth");

                Acg acg = new Acg(acgId, acgName, acgEmail, acgBirth);
                System.out.println(acg);

                //将blob类型的字段下载下来,以文件的方式保存到本地
                Blob acgPhoto = rs.getBlob("acg_photo");
                is = acgPhoto.getBinaryStream();
                fos = new FileOutputStream(new File("src\\君不笑.gif"));

                byte[] buffer = new byte[20];
                int len;
                while((len = is.read(buffer)) != -1){
                    fos.write(buffer,0,len);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if(fos != null)
                fos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if(is != null)
                is.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            JDBCUtils.closeResource(conn,ps,rs);
        }
    }
}

测试结果:

Acg{acgId=4, acgName='叶修', acgeMail='yebuxiu@qzgs.com', acgBirth=2035-05-29}

在这里插入图片描述


  • 7
    点赞
  • 63
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值