Blob数据类型、数据库事务

目录

Blob类型字段

批量插入

数据库事务

Blob类型字段


概述:MySQL中,Blob是一个二进制大型对象,是一个可以存储大量数据的容器,它能容纳不同大小的数据。

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

介绍:MySQL的四种Blob类型 (除了在存储的最大信息量上不同外,他们是等同的),实际使用中根据需要存入的数据大小定义不同的Blob类型。

Blob数据类型、数据库事务_第1张图片

注意:

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

代码实现:插入、查询Blob类型的数据

    //向数据表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, "xuezq@qq.com");
        ps.setObject(3, "1983-7-17");
        //操作Blob类型的变量
        FileInputStream is = new FileInputStream(new File("x.jpg"));
        ps.setBlob(4, is);
        //执行
        ps.execute();
        JDBCUtils.closeResource(conn, ps);
    }

    //查询数据表customers中Blob类型的字段
    @Test
    public void testQuery() {
        Connection conn = null;
        PreparedStatement ps = null;
        InputStream is = null;
        FileOutputStream fos = null;
        ResultSet rs = null;
        try {
            conn = JDBCUtils.getConnection();
            String sql = "select id,name,email,birth,photo from customers where id=?";
            ps = conn.prepareStatement(sql);
            ps.setInt(1, 22);
            //执行
            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 cust = new Customer(id, name, email, birth);
                System.out.println(cust);

                //将Blob类型的字段下载下来,以文件的方式保存在本地
                Blob photo = rs.getBlob("photo");
                is = photo.getBinaryStream();
                fos = new FileOutputStream("xzq.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();
            }
            JDBCUtils.closeResource(conn, ps, rs);
        }
    }

批量插入


概述: 当需要成批插入或者更新记录时,可以采用Java的批量更新机制,这一机制允许多条语句一次性提交给数据库批量处理。

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

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

通常两种批量执行SQL语句的情况:

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

代码实现:向数据表中插入20000条数据

#数据库中提供一个goods表。创建如下:
CREATE TABLE goods(
id INT PRIMARY KEY AUTO_INCREMENT,
NAME VARCHAR(20)
);
    @Test
    public void testInsert4() {
        Connection conn = null;
        PreparedStatement ps = null;
        try {
            long start = System.currentTimeMillis();
            conn = JDBCUtils.getConnection();

            //设置不允许自动提交数据
            conn.setAutoCommit(false);

            String sql = "insert into goods(name)values(?)";
            ps = conn.prepareStatement(sql);
            for (int i = 1; i <= 20000; i++) {
                ps.setObject(1, "name_" + i);

                //1."攒"sql
                ps.addBatch();
                if (i % 500 == 0) {
                    //2.执行
                    ps.executeBatch();
                    //3.清空batch
                    ps.clearBatch();
                }
            }
            //提交数据
            conn.commit();

            long end = System.currentTimeMillis();
            System.out.println("执行的时间:" + (end - start)); //执行的时间:703
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            JDBCUtils.closeResource(conn, ps);
        }
    }

数据库事务


说明:这里只介绍JDBC中的事务处理,基本的数据库事务介绍可以参考博主之前的文章。

概述:一组逻辑操作单元,使数据从一种状态变换到另一种状态。(一组逻辑操作单元,一个或多个DML操作)

特点:

  • 数据一旦提交,就不可回滚
  • 数据什么时候被提交?
    • DDL操作一旦执行,会自动提交,set autocommit = false 对DDL操作失效
    • DML默认情况下一旦执行,就会自动提交,通过set sutocommit = false,取消DML操作的自动提交
    • 关闭数据库连接,数据就会自动的提交
    • 当一个连接对象被创建时,默认情况下是自动提交事务

JDBC程序中让多个SQL语句作为一个事务执行:

  • 调用Connection对象的setAutoCommit(false),以取消自动提交事务
  • 在所有的SQL语句都成功执行后,调用commit(), 方法提交事务
  • 在出现异常时,调用rollback()方法回滚事务

代码实现:用户AA向用户BB转账100

    //**********考虑数据库事务情况下的转账操作****************
    @Test
    public void testUpdateWithTx() {
        Connection conn = null;
        try {
            conn = JDBCUtils.getConnection();
            System.out.println(conn.getAutoCommit()); //true
            
            //1.取消数据的自动提交
            conn.setAutoCommit(false);

            String sql1 = "update user_table set balance = balance - 100 where user = ?";
            update(conn,sql1,"AA");
            //模拟网络异常
            //System.out.println(10/0);
            String sql2 = "update user_table set balance = balance + 100 where user = ?";
            update(conn,sql2,"BB");
            System.out.println("转账成功!");

            //2.提交数据
            conn.commit();
        }catch (Exception e){
            e.printStackTrace();
            //3.回滚数据
            try {
                conn.rollback();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
        finally {
            //修改其为自动提交数据,主要针对于使用数据库连接池时
            try {
                conn.setAutoCommit(true);
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
            JDBCUtils.closeResource(conn,null);
        }
    }

    //通用的增删改操作 ----version  2.0(考虑上事务)
    public int update(Connection conn,String sql,Object ...args) {
        PreparedStatement ps = null;
        try {
            //1.预编译sql语句,返回PreparedStatement实例
            ps = conn.prepareStatement(sql);
            //2.填充占位符
            for (int i = 0; i < args.length; i++) {
                ps.setObject(i+1,args[i]);
            }
            //3.执行
            return ps.executeUpdate();
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            //4.资源关闭
            JDBCUtils.closeResource(null, ps);
        }
        return 0;
    }


你可能感兴趣的