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

来源:互联网 发布:灯塔炒股软件 编辑:程序博客网 时间:2024/06/05 21:57

插入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();}//用完资源后需要关闭/*释放资源:ConnectionStatementResultSet1 尽量晚创建早释放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 {@Testpublic 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数据@Testpublic 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 {@Testpublic 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 {@Testpublic 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 0
原创粉丝点击