您的位置:首页 > 数据库

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

2016-10-17 03:03 381 查看

插入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();
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  jdbc 图片 批处理