JDBC 之插入Blob(图片)& 批处理 & 数据库事务

插入Blob字段类型(如图片) 实现批处理和 数据库事务的一致性
一、插入Blob类型数据(如:图片)
使用JDBC来写入Blob型数据到数据库中
数据库中的Blob字段比long字段的性能要好,可以用来保存如图片之类的二进制数据。

BLOB字段由两部分组成:数据(值)和指向数据的指针(定位器)。
尽管值与表自身一起存储,但是一个BLOB列并不包含值,仅有它的定位指针。
为了使用大对象,程序必须声明定位器类型的本地变量。
当数据库内部LOB被创建时,定位器被存放在列中,值被存放在LOB段中,
LOB段是在数据库内部表的一部分。
因为Blob自身有一个cursor,当写入Blob字段必须使用指针(定位器)
对Blob进行操作,因而在写入Blob之前,必须获得指针(定位器)才能进行写入
如何获得Blob的指针(定位器) :需要先插入一个empty的blob,
这将创建一个blob的指针,然后再把这个empty的blob的指针查询出来,
这样通过两步操作,就获得了blob的指针,可以真正的写入blob数据了。

<1>第一步:连接数据库和释放资源的JDBCUtils是不可少的

封装使用C3P0获取连接和关闭连接 这两个方法封装如下:

public class JDBCUtils {

//数据库连接池值应该被初始化一次放在静态代码块中
private static DataSource datasource=null;
static{
    datasource =new ComboPooledDataSource("helloc3p0");
}
public static  Connection getConnection() throws SQLException{

    return datasource.getConnection();
}

//用完资源后需要关闭

/*释放资源:
Connection
Statement
ResultSet
1 尽量晚创建早释放
2 后使用的先关闭*/

public static void release(ResultSet rs,Statement statement,Connection conn){
     if(rs!=null){
            try{
                rs.close();
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }

      if(statement!=null){
    try{
        statement.close();
    } catch (Exception e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}
       if(conn!=null){
        try {
            conn.close();
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
    }
  }
}

<2> 编码格式 数据库utf8

<2>第二步:实现插入Blob类型(图片)的数据如下:

public class TestBlob {
@Test
public void testInsert() throws Exception{
    //获取连接
    Connection connection = JDBCUtils.getConnection();

    PreparedStatement statement = connection.prepareStatement("insert into star values(null,'mnls',?)");

    //插入图片占位符值 图片存储在src包下
    statement.setBlob(1, new FileInputStream("src/mnls.jpg"));

    //执行插入图片
    int executeUpdate = statement.executeUpdate();
    if (executeUpdate>0) {
        System.out.println("success");
    } else {
        System.out.println("failure");
    }
    JDBCUtils.release(connection, statement, null);
}

<2>第三步:实现将数据库中Blob类型(图片)的数据取出:

//查询blob数据
@Test
public void testRead() throws Exception{
    Connection connection = DBUtils.getConnection();

    PreparedStatement statement = connection.prepareStatement("select * from star where id=1");
    ResultSet set = statement.executeQuery();
    if (set.next()) {

        Blob blob = set.getBlob("photo");

        //获取二进制流对象  ★
        InputStream stream = blob.getBinaryStream();

        //一边读一边写 写入src下存为copy.jpg
        //将读到的数据转换成字符数组(方法如下)
        byte[] arrs = StreamUtils.streamToByteArray(stream);

        FileOutputStream fos = new FileOutputStream("src/copy.jpg");

        fos.write(arrs);

        fos.close();
    }
    DBUtils.release(connection, statement, set);
}

}

//将输入流转换成byte[] 如下

public class StreamUtils {
/**
 * 
 * 将 输入流 转换成byte[]
 * @param is
 * @return
 */
public static byte[] streamToByteArray(InputStream is) throws IOException{

    //创建字节数组的输出流
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    byte[] b=new byte[1024];

    int len;
    while((len=is.read(b))!=-1){
        baos.write(b, 0, len);//写到字节数组的输出流
    }
    is.close();

    baos.close();

    return  baos.toByteArray();
}
}

二、JDBC之批处理操作

描述:

批量处理JDBC语句提高处理速度 当需要成批插入或者更新记录时。
可以采用Java的批量更新机制,这一机制允许多条语句一次性
提交给数据库批量处理。通常情况下比单独提交处理更有效率
JDBC的批量处理语句包括下面两个方法:
addBatch(String):添加需要批量处理的SQL语句或是参数;
executeBatch():执行批量处理语句;
clearBatch():清空缓存的数据
通常我们会遇到两种批量执行SQL语句的情况:
多条SQL语句的批量处理;
一个SQL语句的批量传参;

<1> 注意url的配置 和数据库与java项目的编码一致utf8

<2> 加入jar包commons-dbutils-1.3.jar

url:

jdbc:mysql://localhost:3306/test?rewriteBatchedStatements=true

<3>实现批处理如下

/**
 * 此类用于演示批处理
 * @author liyuting
 *
 */
public class TestBatch {

@Test
public void testBatch(){
    Connection connection=null;
    PreparedStatement statement =null;

    try {
        connection = JDBCUtils.getConnection();
    statement= connection.prepareStatement
    ("insert into 表名 values(null,?,'男','38835@qq.com',now())");

        for (int i =1; i <=20000; i++) {

        statement.setString(1, "李四"+i);

        statement.addBatch();//添加到批处理的语句中

        if (i%500==0) {//每500条sql语句执行一次

            statement.executeBatch();//真正的执行

            statement.clearBatch();//清空缓存
            }
        }
    } catch (SQLException e) {
        e.printStackTrace();
    }
    finally{
        JDBCUtils.release(connection, statement, null);
    }

}

}

三、JDBC之数据库事务(控制多条sql执行中其中一条会出现异常)

<1>描述:

JDBC 事务处理:
当一个连接对象被创建时,默认情况下是自动提交事务:
每次执行一个 SQL 语句时,如果执行成功,
就会向数据库自动提交,而不能回滚
为了让多个 SQL 语句作为一个事务执行:
调用 Connection 对象的 setAutoCommit(false); 
以取消自动提交事务
在所有的 SQL 语句都成功执行后,调用 commit(); 方法提交事务
在出现异常时,调用 rollback(); 方法回滚事务
若此时 Connection 没有被关闭, 则需要恢复其自动提交状态

<2>实现如下:

/**
 * 此类用于演示演示事务
 * @author liyuting
 *
 */
public class TestTransaction {
@Test
public void testBatch(){
    Connection connection = null;
    try {

        //1获取连接
            connection=DBUtils.getConnection();

         //2.开启事务 (start transaction)
         connection.setAutoCommit(false);//取消每一行的自动提交

         //执行一条修改语句
         update(connection,"update users set name='张三' where id=?",1);

         int i = 10/1;//模拟异常

        //执行第二条修改语句
         update(connection,"update users set name='李四' where id=?",2);

         //提交事务(commit)
         connection.commit();
    } catch (SQLException e) {

        //回滚事务(rollback)
        try {
            connection.rollback();
        } catch (SQLException e1) {
            e1.printStackTrace();
        }
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值