JDBC(二)(1)

本文涉及的产品
云数据库 RDS MySQL,集群版 2核4GB 100GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,高可用版 2核4GB 50GB
简介: JDBC(二)(1)

第4章 操作BLOB类型字段

4.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服务。

代码结构:

4.2 向数据表中插入大数据类型

BlobTest.java

//向数据表customers中插入Blob类型的字段
  @Test
  public void testInsert() throws Exception{
    Connection conn = JDBCUtils.getConnection();
    String sql = "insert into customers(name,email,birth,photo)values(?,?,?,?)";
    
    PreparedStatement ps = conn.prepareStatement(sql);
    
    ps.setObject(1,"袁浩");
    ps.setObject(2, "yuan@qq.com");
    ps.setObject(3,"1992-09-08");
    FileInputStream is = new FileInputStream(new File("girl.jpg"));
    ps.setBlob(4, is);
    
    ps.execute();
    
    JDBCUtils.closeResource(conn, ps);
    
  }

4.3 修改数据表中的Blob类型字段

Connection conn = JDBCUtils.getConnection();
String sql = "update customers set photo = ? where id = ?";
PreparedStatement ps = conn.prepareStatement(sql);
// 填充占位符
// 操作Blob类型的变量
FileInputStream fis = new FileInputStream("coffee.png");
ps.setBlob(1, fis);
ps.setInt(2, 25);
ps.execute();
fis.close();
JDBCUtils.closeResource(conn, ps);

4.4 从数据表中读取大数据类型

String sql = "SELECT id, name, email, birth, photo FROM customer WHERE id = ?";
conn = getConnection();
ps = conn.prepareStatement(sql);
ps.setInt(1, 8);
rs = ps.executeQuery();
if(rs.next()){
  Integer id = rs.getInt(1);
    String name = rs.getString(2);
  String email = rs.getString(3);
    Date birth = rs.getDate(4);
  Customer cust = new Customer(id, name, email, birth);
    System.out.println(cust); 
    //读取Blob类型的字段
  Blob photo = rs.getBlob(5);
  InputStream is = photo.getBinaryStream();
  OutputStream os = new FileOutputStream("c.jpg");
  byte [] buffer = new byte[1024];
  int len = 0;
  while((len = is.read(buffer)) != -1){
    os.write(buffer, 0, len);
  }
    JDBCUtils.closeResource(conn, ps, rs);
    
  if(is != null){
    is.close();
  }
    
  if(os !=  null){
    os.close();
  }
    
}

第5章 批量插入

5.1 批量执行SQL语句

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

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

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

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

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

5.2 高效的批量插入

举例:向数据表中插入20000条数据

  • 数据库中提供一个goods表
CREATE TABLE goods(
id INT PRIMARY KEY AUTO_INCREMENT,
NAME VARCHAR(20)
);

5.2.1 实现一:使用Statement

InsertTest.java

Connection conn = JDBCUtils.getConnection();
Statement st = conn.createStatement();
for(int i = 1;i <= 20000;i++){
  String sql = "insert into goods(name) values('name_' + "+ i +")";
  st.executeUpdate(sql);
}

5.2.2 实现二:使用PreparedStatement

long start = System.currentTimeMillis();
    
Connection conn = JDBCUtils.getConnection();
    
String sql = "insert into goods(name)values(?)";
PreparedStatement ps = conn.prepareStatement(sql);
for(int i = 1;i <= 20000;i++){
  ps.setString(1, "name_" + i);
  ps.executeUpdate();
}
    
long end = System.currentTimeMillis();
System.out.println("花费的时间为:" + (end - start));//82340
    
    
JDBCUtils.closeResource(conn, ps);

5.2.3 实现三

/*
 * 修改1: 使用 addBatch() / executeBatch() / clearBatch()
 * 修改2:mysql服务器默认是关闭批处理的,我们需要通过一个参数,让mysql开启批处理的支持。
 *     ?rewriteBatchedStatements=true 写在配置文件的url后面
 * 修改3:使用更新的mysql 驱动:mysql-connector-java-5.1.37-bin.jar
 * 
 */
@Test
public void testInsert1() throws Exception{
  long start = System.currentTimeMillis();
    
  Connection conn = JDBCUtils.getConnection();
    
  String sql = "insert into goods(name)values(?)";
  PreparedStatement ps = conn.prepareStatement(sql);
    
  for(int i = 1;i <= 1000000;i++){
    ps.setString(1, "name_" + i);
      
    //1.“攒”sql
    ps.addBatch();
    if(i % 500 == 0){
      //2.执行
      ps.executeBatch();
      //3.清空
      ps.clearBatch();
    }
  }
    
  long end = System.currentTimeMillis();
  System.out.println("花费的时间为:" + (end - start));//20000条:625                                                                         //1000000条:14733  
    
  JDBCUtils.closeResource(conn, ps);
}

5.2.4 实现四

/*
* 层次四:在层次三的基础上操作
* 使用Connection 的 setAutoCommit(false)  /  commit()
*/
@Test
public void testInsert2() throws Exception{
  long start = System.currentTimeMillis();
    
  Connection conn = JDBCUtils.getConnection();
    
  //1.设置为不自动提交数据
  conn.setAutoCommit(false);
    
  String sql = "insert into goods(name)values(?)";
  PreparedStatement ps = conn.prepareStatement(sql);
    
  for(int i = 1;i <= 1000000;i++){
    ps.setString(1, "name_" + i);
      
    //1.“攒”sql
    ps.addBatch();
      
    if(i % 500 == 0){
      //2.执行
      ps.executeBatch();
      //3.清空
      ps.clearBatch();
    }
  }
    
  //2.提交数据
  conn.commit();
    
  long end = System.currentTimeMillis();
  System.out.println("花费的时间为:" + (end - start));//1000000条:4978 
    
  JDBCUtils.closeResource(conn, ps);
}

第6章:DAO及相关实现类

  • DAO:Data Access Object访问数据信息的类和接口,包括了对数据的CRUD(Create、Retrival、Update、Delete),而不包含任何业务相关的信息。有时也称作:BaseDAO
  • 作用:为了实现功能的模块化,更有利于代码的维护和升级。
  • 下面是尚硅谷JavaWeb阶段书城项目中DAO使用的体现:

  • 层次结构:

BaseDAO.java

package com.atguigu.bookstore.dao;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import org.apache.commons.dbutils.handlers.ScalarHandler;
/**
 * 定义一个用来被继承的对数据库进行基本操作的Dao
 * 
 * @author HanYanBing
 *
 * @param <T>
 */
public abstract class BaseDao<T> {
  private QueryRunner queryRunner = new QueryRunner();
  // 定义一个变量来接收泛型的类型
  private Class<T> type;
  // 获取T的Class对象,获取泛型的类型,泛型是在被子类继承时才确定
  public BaseDao() {
    // 获取子类的类型
    Class clazz = this.getClass();
    // 获取父类的类型
    // getGenericSuperclass()用来获取当前类的父类的类型
    // ParameterizedType表示的是带泛型的类型
    ParameterizedType parameterizedType = (ParameterizedType) clazz.getGenericSuperclass();
    // 获取具体的泛型类型 getActualTypeArguments获取具体的泛型的类型
    // 这个方法会返回一个Type的数组
    Type[] types = parameterizedType.getActualTypeArguments();
    // 获取具体的泛型的类型·
    this.type = (Class<T>) types[0];
  }
  /**
   * 通用的增删改操作
   * 
   * @param sql
   * @param params
   * @return
   */
  public int update(Connection conn,String sql, Object... params) {
    int count = 0;
    try {
      count = queryRunner.update(conn, sql, params);
    } catch (SQLException e) {
      e.printStackTrace();
    } 
    return count;
  }
  /**
   * 获取一个对象
   * 
   * @param sql
   * @param params
   * @return
   */
  public T getBean(Connection conn,String sql, Object... params) {
    T t = null;
    try {
      t = queryRunner.query(conn, sql, new BeanHandler<T>(type), params);
    } catch (SQLException e) {
      e.printStackTrace();
    } 
    return t;
  }
  /**
   * 获取所有对象
   * 
   * @param sql
   * @param params
   * @return
   */
  public List<T> getBeanList(Connection conn,String sql, Object... params) {
    List<T> list = null;
    try {
      list = queryRunner.query(conn, sql, new BeanListHandler<T>(type), params);
    } catch (SQLException e) {
      e.printStackTrace();
    } 
    return list;
  }
  /**
   * 获取一个但一值得方法,专门用来执行像 select count(*)...这样的sql语句
   * 
   * @param sql
   * @param params
   * @return
   */
  public Object getValue(Connection conn,String sql, Object... params) {
    Object count = null;
    try {
      // 调用queryRunner的query方法获取一个单一的值
      count = queryRunner.query(conn, sql, new ScalarHandler<>(), params);
    } catch (SQLException e) {
      e.printStackTrace();
    } 
    return count;
  }
}

JDBC(二)(2)+https://developer.aliyun.com/article/1556660

相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
相关文章
|
9月前
|
Java 关系型数据库 MySQL
JDBC知识【JDBC概述】第一章
JDBC知识【JDBC概述】第一章
|
2天前
|
Java 数据库连接 数据库
JDBC(一)(3)
JDBC(一)(3)
3 0
|
2天前
|
监控 Java 数据库连接
JDBC(二)(2)
JDBC(二)(2)
4 0
|
2天前
|
SQL 存储 Java
JDBC(一)(2)
JDBC(一)(2)
6 0
|
2天前
|
存储 Java 数据库连接
JDBC(一)(1)
JDBC(一)(1)
7 0
|
2天前
|
SQL Java 关系型数据库
JDBC(二)(3)
JDBC(二)(3)
3 0
|
9月前
|
Java 数据库连接 数据库
JDBC知识【JDBC练习】第五章
JDBC知识【JDBC练习】第五章
|
SQL Oracle Java
JDBC 的原理 | 学习笔记
快速学习 JDBC 的原理
137 0
JDBC 的原理 | 学习笔记
|
SQL Java 数据库连接
JDBC(一) 如何使用JDBC进行编程?
JDBC常见操作总结(详略分明)
|
Java 关系型数据库 MySQL
JDBC - 基础篇
JDBC - 基础篇
98 0
JDBC - 基础篇