• JDBC-day03(BLOB类型字段,批量插入)


    四:操作BLOB类型字段

    1.MySQL BLOB类型

    • 在MySQL中,BLOB是一个二进制大型对象,是一个可以存储大量数据的容器,它能容纳不同大小的数据。可以用来存储图片,视频等

    • 插入BLOB类型的数据必须使用PreparedStatement,因为BLOB类型的数据无法使用字符串拼接写的。

    • MySQL的四种BLOB类型(除了在存储的最大信息量上不同外,他们是等同的)
      在这里插入图片描述

    • 实际使用中根据需要存入的数据大小定义不同的BLOB类型。

    • 如果在指定了相关的Blob类型以后,还报错:xxx too large,那么在mysql的安装目录下,找my.ini文件加上如下的配置参数: max_allowed_packet=16M。同时注意:修改了my.ini文件之后,需要重新启动mysql服务。

    2.向数据表customer中插入Blob类型的字段

    public class BlobTest {
    	@Test
    	public void testInsert() throws Exception {
    		Connection conn = null;                          
    		PreparedStatement ps = null;
    		try {
    			conn = JDBC_Utils.getConnection();
    			String sql = "insert into customers(name,email,birth,photo)values(?,?,?,?)";
    			
    			ps = conn.prepareStatement(sql);
    			
    			ps.setObject(1, "张杰");
    			ps.setObject(2, "ZhangJie@168.com");
    			ps.setObject(3, "1992-09-08");
    			FileInputStream is = new FileInputStream(new File("zhangjie.jpg"));
    			//如果文件大于1MB,可能会报xxx too large错误,解决方法参照上面的解决方式
    			ps.setBlob(4, is);
    			
    			ps.execute();
    		} catch (Exception e) {
    			e.printStackTrace();
    		}finally {
    			JDBC_Utils.closeResource(conn, ps);
    		}
    			
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    注:在工作目录下要有zhangjie.jpg,否则会提示找不到文件

    3.查询数据表customer中的Blob字段

    	@Test
    	public void testQuery(){
    		Connection conn = null;      
    		PreparedStatement ps = null;
    		ResultSet rs = null; 
    		InputStream is = null;
    		FileOutputStream fos = null;
    		try { 
    			conn = JDBC_Utils.getConnection();
    			String sql = "select id,name,email,birth,photo from customers where id = ?"; 
    			ps = conn.prepareStatement(sql);
    			ps.setInt(1,21);
    			
    			rs = ps.executeQuery(); 
    			if(rs.next()) { 
    				//使用列的别名来查找
    				int id = rs.getInt("id");
    				String name = rs.getString("name");
    				String email = rs.getString("email"); 
    				Date birth = rs.getDate("birth");
    				
    				Customer customer = new Customer(id,name,email,birth);
    				System.out.println(customer); 
    				
    				//将Blob类型的字段下载下来,以文件的形式保留到本地
    				Blob photo = rs.getBlob("photo");
    				is = photo.getBinaryStream();
    				fos = new FileOutputStream("singer.jpg");
    				byte[] buffer = new byte[1024];
    				int len;
    				while((len = is.read(buffer)) != -1) { 
    					fos.write(buffer, 0, len);
    				}
    			}
    		} catch (Exception e) {
    			e.printStackTrace();
    		}finally {
    			try { 
    				if(is != null) 
    					is.close(); 
    			} catch (IOException e) {
    				e.printStackTrace();
    			}
    			try { 
    				if(fos != null) 
    					fos.close();
    			} catch (IOException e) {
    				e.printStackTrace();
    			}
    			JDBC_Utils.closeResource(conn, ps, rs); 
    		
    		}
    		
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54

    五:批量插入

    1.批量操作

    当需要成批插入或者更新记录时,可以采用Java的批量更新机制,这一机制允许多条语句一次性提交给数据库批量处理。通常情况下比单独提交处理更有效率

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

    • addBatch(String):添加需要批量处理的SQL语句或是参数;
    • executeBatch():执行批量处理语句;
    • clearBatch():清空缓存的数据

    通常我们会遇到两种批量执行SQL语句的情况:

    • 多条SQL语句的批量处理;
    • 一个SQL语句的批量传参;

    2.高效的批量插入

    • 使用PreparedStatement实现批量数据操作
    • update,delete本身就具有批量操作的效果
    • 此时的批量操作,主要指批量插入

    例: 题目向goods表添加100万条数据

     CREATE TABLE goods(
     id INT PRIMARY KEY AUTO_INCREMENT,       
     NAME VARCHAR(25)
    );
    
    • 1
    • 2
    • 3
    • 4
    import java.sql.Connection;                                      
    import java.sql.PreparedStatement;
    
    import org.junit.Test;
    
    import com.jdbc.util.JDBC_Utils;
    
    public class InsertTest {
    	//方式一:使用Statement批量插入数据(略)
    	//方式二:使用PreparedStatement批量插入数据
    	@Test
    	public void testInsert1() {
    		Connection conn = null;
    		PreparedStatement ps = null;
    		try {
    			long start = System.currentTimeMillis();
    			conn = JDBC_Utils.getConnection();
    			String sql = "insert into goods(name)values(?)";
    			ps = conn.prepareStatement(sql);
    			for(int i = 1;i <= 1000000;i++) {
    				ps.setObject(1,"name_" + i);
    				
    				ps.execute();
    			}
    			long end = System.currentTimeMillis();
    			System.out.println("插入花费时间为:" + (end - start) + "毫秒");//1350941毫秒---8473毫秒---5857毫秒
    		} catch (Exception e) {
    			e.printStackTrace();
    		}finally {
    			JDBC_Utils.closeResource(conn, ps);
    		}	
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    方式三:使用addBatch(),executeBatch(),clearBatch()批量插入数据

    • mysql服务器默认关闭批处理,需要通过在url后添加?rewriteBatchedStatements=true来进行开启,不是mysqld的配置文件,是数据库连接的配置文件,即jdbc.properties

    • mysql驱动需要5.1.37及以上版本

      @Test
      public void testInsert2() {
      	Connection conn = null;                                                        
      	PreparedStatement ps = null;
      	try { 
      		long start = System.currentTimeMillis();
      		conn = JDBC_Utils.getConnection();
      		String sql = "insert into goods(name)values(?)"; 
      		ps = conn.prepareStatement(sql);
      		for(int i = 1;i <= 1000000;i++) {
      			ps.setObject(1,"name_" + i);
      			//1."攒"SQL
      			ps.addBatch();
      			if(i % 500 == 0) {
      				//2.执行batch
      				ps.executeBatch();
      				//3.清空batch
      				ps.clearBatch(); 
      			}
      		}
      		long end = System.currentTimeMillis();
      		System.out.println("插入花费时间为:" + (end - start) + "毫秒");
      	} catch (Exception e) {
      		e.printStackTrace();
      	}finally {
      		JDBC_Utils.closeResource(conn, ps);
      	}
      }
      
      
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30

    方式四:设置连接不允许自动提交数据

    	@Test
    	public void testInsert3() {
    		Connection conn = null;          
    		PreparedStatement ps = null;
    		try {
    			long start = System.currentTimeMillis();
    			conn = JDBC_Utils.getConnection();
    			//设置不允许自动提交,默认执行SQL,就自动提交到数据库
    			conn.setAutoCommit(false);
    			String sql = "insert into goods(name)values(?)";
    			ps = conn.prepareStatement(sql);
    			for(int i = 1;i <= 1000000;i++) {
    				ps.setObject(1,"name_" + i);
    				//1."攒"SQL
    				ps.addBatch();
    				if(i % 500 == 0) {
    					//2.执行batch
    					ps.executeBatch();
    					//3.清空batch
    					ps.clearBatch();
    				}
    			}
    			//提交数据
    			conn.commit();
    			long end = System.currentTimeMillis();
    			System.out.println("插入花费时间为:" + (end - start) + "毫秒");
    		} catch (Exception e) {
    			e.printStackTrace();
    		}finally {
    			JDBC_Utils.closeResource(conn, ps);
    		}
    	}
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34

    其中可能会出现不少的小问题,请多多包含
    感谢大家的支持,关注,评论,点赞!
    参考资料:尚硅谷_宋红康_JDBC核心技术

  • 相关阅读:
    经纬恒润48V BMS助力Stellantis量产落地
    黑马点评-短信登录业务
    【面经】联想大数据开发面经
    如何手撸一个自有知识库的RAG系统
    2022鹏城杯web
    Android Live Edit 给 Android开发者带来的福音
    STM32F103VET6基于STM32CubeMX创建定时器中断控制LED闪烁
    【PyQt】(自制类)处理鼠标点击逻辑
    Set集合
    k8s-服务网格实战-配置 Mesh(灰度发布)
  • 原文地址:https://blog.csdn.net/weixin_51202460/article/details/133661291