JDBC+Hibernate将Blob数据写入Oracle

Oracle的Blob字段比较特殊,他比long字段的性能要好很多,可以用来保存例如图片之类的二进制数据。

  写入Blob字段和写入其它类型字段的方式非常不同,因为Blob自身有一个cursor,你必须使用cursor对blob进行操作,因而你在写入Blob之前,必须获得cursor才能进行写入,那么如何获得Blob的cursor呢?

  这需要你先插入一个empty的blob,这将创建一个blob的cursor,然后你再把这个empty的blob的cursor用select查询出来,这样通过两步操作,你就获得了blob的cursor,可以真正的写入blob数据了。

  看下面的JDBC的demo,把oraclejdbc.jar这个二进制文件写入数据库表javatest的content字段(这是一个blob型字段)

import java.sql.*;
import java.io.*;
import oracle.sql.*;
public class WriteBlob {

public static void main(String[] args) {

 try {
  DriverManager.registerDriver(new oracle.jdbc.driver.OracleDriver());
  Connection conn = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:orcl","fankai","fankai");
  conn.setAutoCommit(false);

  BLOB blob = null;

  PreparedStatement pstmt = conn.prepareStatement("insert into javatest(name,content) values(?,empty_blob())");
  pstmt.setString(1,"fankai");
  pstmt.executeUpdate();
  pstmt.close();

  pstmt = conn.prepareStatement("select content from javatest where name= ? for update");
  pstmt.setString(1,"fankai");
  ResultSet rset = pstmt.executeQuery();
  if (rset.next()) blob = (BLOB) rset.getBlob(1);

  String fileName = "oraclejdbc.jar";
  File f = new File(fileName);
  FileInputStream fin = new FileInputStream(f);
  System.out.println("file size = " + fin.available());

  pstmt = conn.prepareStatement("update javatest set content=? where name=?");

  OutputStream out = blob.getBinaryOutputStream();

  int count = -1, total = 0;
  byte[] data = new byte[(int)fin.available()];
  fin.read(data);
  out.write(data);
  /*
  byte[] data = new byte[blob.getBufferSize()]; 另一种实现方法,节省内存
  while ((count = fin.read(data)) != -1) {
   total += count;
   out.write(data, 0, count);
  }
  */

  fin.close();
  out.close();

  pstmt.setBlob(1,blob);
  pstmt.setString(2,"fankai");

  pstmt.executeUpdate();
  pstmt.close();

  conn.commit();
  conn.close();
 } catch (SQLException e) {
   System.err.println(e.getMessage());
  e.printStackTrace();
 } catch (IOException e) {
  System.err.println(e.getMessage());
 }
}

}


  仔细看上例,分三步:

  1、插入空blob

into javatest(name,content) values(?,empty_blob());


  2、获得blob的cursor

select content from javatest where name= ? for update;


  注意!!!必须加for update,这将锁定该行,直至该行被修改完毕,保证不产生并发冲突。

  3、update javatest set content=? where name=

  用cursor往数据库写数据

  这里面还有一点要提醒大家:

  JDK1.3带的JDBC2.0规范是不完善的,只有读Blob的接口,而没有写Blob的接口,JDK1.4带的JDBC3.0加入了写Blob的接口。你可以使用JDBC3.0的接口,也可以直接使用Oracle的JDBC的API,我在上例中使用了Oracle的JDBC的API。

  另外要注意的是:

java.sql.Blob

oracle.sql.BLOB


  注意看blob的大小写,是不一样的。写程序的时候不要搞混了。

  下面看看用Hibernate怎么写,原理是一样的,也要分三步,但是代码简单很多

  这是Cat对象定义

package com.fankai;

import java.sql.Blob;

public class Cat {
 private String id;
 private String name;
 private char sex;
 private float weight;
 private Blob image;
 public Cat() { }

 public String getId() { return id; }
 public void setId(String id) { this.id = id; }

 public String getName() { return name; }
 public void setName(String name) { this.name = name; }

 public char getSex() { return sex; }
 public void setSex(char sex) { this.sex = sex; }

 public float getWeight() { return weight; }
 public void setWeight(float weight) { this.weight = weight; }

 public Blob getImage() { return image; }
 public void setImage(Blob image) { this.image = image;}
}


  这是Cat.hbm.xml

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping SYSTEM "http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd">

<hibernate-mapping>
<class name="com.fankai.Cat" table="cat">
<!--jcs-cache usage="read-only"/-->
<id name="id" unsaved-value="null">
<generator class="uuid.hex"/>
</id>
<property name="name" length="16" not-null="true"/>
<property name="sex" length="1" not-null="true"/>
<property name="weight" />
<property name="image" />
</class>
</hibernate-mapping>


  下面是完整的用Hibernate写入Blob的例子,相比JDBC,已经简单轻松多了,也不用写那些Oracle特殊的sql了:

package com.fankai;

import java.sql.Blob;
import net.sf.hibernate.*;
import oracle.sql.*;
import java.io.*;

public class TestCatHibernate {
 public static void testBlob() {
  Session s = null;
  byte[] buffer = new byte[1];
  buffer[0] = 1;
  try {
   SessionFactory sf = HibernateSessionFactory.getSessionFactory();
   s = sf.openSession();
   Transaction tx = s.beginTransaction();
   Cat c = new Cat();
   c.setName("Robbin");
   c.setImage(Hibernate.createBlob(buffer));
   s.save(c);
   s.flush();
   s.refresh(c, LockMode.UPGRADE);
   BLOB blob = (BLOB) c.getImage();
   OutputStream out = blob.getBinaryOutputStream();
   String fileName = "oraclejdbc.jar";
   File f = new File(fileName);
   FileInputStream fin = new FileInputStream(f);
   int count = -1, total = 0;
   byte[] data = new byte[(int)fin.available()];
   fin.read(data);
   out.write(data);
   fin.close();
   out.close();
   s.flush();
   tx.commit();

  } catch (Exception e) {
   System.out.println(e.getMessage());
  } finally {
   if (s != null)
   try {
    s.close();
   } catch (Exception e) {}
  }
 }
}
《HiVT: Hierarchical Vector Transformer for Multi-Agent Motion Prediction》论文阅读之HiVT 目录摘要1.介绍2.相关工作3.方法3.1. 总体框架3.2 场景表示 3.3 分层向量Transformer3.3.1 局部编码器3.3.2 全局交互模块3.3.3 多模态未来解码器3.4 训练4.实验4.1 实验设置4.2 消融研究 4.3. 结果5.结论 准确预测周围交通参与者的未来运动对于自动驾驶车辆的安全至关重要。最近,矢量化方法由于能够捕捉交通场景中的复杂交互而在运动预测领域占据主导地位。然而,现有的方法忽略了问题的对称性并且受到昂贵的计算成本的影响,面临着在不牺牲预测性能的情况 阅读详情

相关推荐

基于高精度三维机器视觉的新能源汽车锂电池表面缺陷检测

在机器视觉行业迅速发展的背景下,市场上提供了功能强大且种类齐全的3D相机系列,可以满足锂电池从电芯到模组各个工艺和工位的3D检测需求。

Hinyeung_Limited的博客 1132

sqlite3数据库之blob数据类型读写

sqlite3数据库之blob数据类型读写 近期在开发过程中需要在数据库中保存二进制文件,于是去了解了一下sqlite3的数据类型,发现blob可以存储二进制数据。 但是blob要如何操作呢?用什么语句呢? 其实它是需要操作sqlite3库的一些底层API来实现。 下面我们就来做实验。 先上测试代码: #include "Wdebug.h" #include "sqlite/Wsqlite.h" #include <stdlib.h> #define TABLE_NAME "TEST_BL

Programmer_Dong的博客 1万+

改进爬山算法之六:随机重启爬山算法(Random-Restart Hill Climbing,RRHC)

随机重启爬山算法(Random-Restart Hill Climbing,RRHC)是爬山算法的一种改进策略,是一种启发式搜索算法,旨在通过随机重启来克服传统爬山算法容易陷入局部最优解的局限性,并增加找到全局最优解的概率。随机重启爬山算法通过在多次运行中不断尝试不同的初始解,并在每次运行中执行标准的爬山算法,最终选择所有运行中找到的最佳解作为最终结果。(1)计算复杂度:由于需要多次运行爬山算法,因此算法的计算复杂度可能较高,特别是在解空间较大或每次迭代需要较长时间的情况下。

搏博的专栏 2205

用hibernate存入和写出Blob、Clob

Person .java package www.youkuaiyun.com.blank.bean; import java.io.Serializable; import java.sql.Blob; import java.sql.Clob; public class Person implements Serializable{ /** * */ private st

yanmei的专栏 2874

postgresql 数据库 timescaledb 函数time_bucket_gapfill()报错解决及更换 license

最近在工作中使用postgresql 和 timescaledb 的time_bucket_gapfill()函数 报错,让更换license,在网上找了一大圈,没有找到,最后解决了这个问题,这篇文章记录我的解决办法查看timescaledb.license参数命令:show timescaledb.license;修改命令: 结果不行,报错如下:lter system set timescaledb.license=‘timescale’;那只能换包了如果出现上面那种情况,那我们只能先从官网上下载带 '

yang_z_1的博客 3249

Nginx国密HTTPS实战:SM2双证书部署与TongSuo编译指南

HTTPS作为保障网络通信安全的基石,其核心在于SSL/TLS协议与公钥基础设施(PKI)。它通过非对称加密实现身份认证与密钥交换,再结合对称加密确保数据传输的机密性与完整性。在金融、政务等对自主可控有严格要求的领域,采用符合国家密码管理局标准的国密算法(SM2/SM3/SM4)替代国际通用算法(如RSA/SHA-256/AES),已成为满足安全合规要求的关键技术路径。国密SSL不仅是一套算法替换,更涉及从底层密码库到上层应用服务的完整技术栈改造。其核心价值在于实现密码技术的自主可控,提升特定场景下的安全防

weixin_29323365的博客 497

向数据库中存储以及读取BLOB对象

对LOB类型的数据是很特殊的,读取以及存储都与一般的类型不同:1、存储BLOB类型:首先需要建一个directory ,用来存放图片的文件夹地址:create or replace directory BLOBDIR as D:/oradata/Pic;grant read,write on directory BLOBDIR to  daimin;新建表CREATE

daimin's BLOG 1832

张量/数组存储方式与向量化展开/展平、view、reshape、permute对比

对于一个Tensor来说,我们可以认为它有两种存储方式。

欢迎关注,共同进步! 3434

JDBC+Hibernate将Blob数据写入Oracle(转载)

Oracle的Blob字段比较特殊,他比long字段的性能要好很多,可以用来保存例如图片之类的二进制数据。   写入Blob字段和写入其它类型字段的方式非常不同,因为Blob自身有一个cursor,你必须使用cursor对blob进行操作,因而你在写入Blob之前,必须获得cursor才能进行写入,那么如何获得Blob的cursor呢?   这需要你先插入一个empty的blob,这将创建一个bl

E.N.O 1055

论文阅读《Eigen-GNN: A Graph Structure Preserving Plug-in for GNNs》

好久没看论文了,感觉好生疏 关于这篇文章的大致脉络,这篇文章已经介绍过了。

且视他人之疑目如盏盏鬼火,大胆地去走你的夜路 461

算法笔记 经典取石子游戏总结 博弈论

经典取石子游戏总结 1.巴什博弈 有一堆石子共n个,A和B轮流取,A先取。每次最少取1个,最多取m个,先取完者获胜(即没有石子取的人失败)。A与B都足够聪明,问A能否获胜。 结论:当n%(m+1)!=0时A必胜,否则必败。 2.斐波那契博弈 有一堆石子共n个,A和B轮流取,A先取。每次最少取1个。第一次不能取完。从第二次开始,每个人取的石子数至少为1,至多为前一个人取的石子数的2倍。先取完者获胜。...

CraigMC的博客 2936

[转载]JDBC+Hibernate将Blob数据写入Oracle

Oracle的Blob字段比较特殊,他比long字段的性能要好很多,可以用来保存例如图片之类的二进制数据。   写入Blob字段和写入其它类型字段的方式非常不同,因为Blob自身有一个cursor,你必须使用cursor对blob进行操作,因而你在写入Blob之前,必须获得cursor才能进行写入,那么如何获得Blob的cursor呢?  这需要你先插入一个empty的blob,这将创建一个blo

593

基于Simulink与MATLAB的七轴OpenArm机械臂逆运动学仿真与轨迹规划完整指南

本文详细介绍了七自由度OpenArm机械臂在MATLAB/Simulink环境下的运动学仿真与轨迹规划实现方法。首先建立了机械臂的DH参数模型,验证了正运动学计算;随后提出了两种逆运动学求解算法(数值迭代法和臂型角参数化解析法)的MATLAB实现方案;最后在Simulink中搭建了完整的轨迹规划与控制系统。研究解决了七自由度冗余机械臂特有的多解性、奇异性和关节限位约束等核心问题,为OpenArm机械臂的运动控制提供了完整的技术方案和可运行代码实现。

AI的内部世界的博客 681

使用JDBC和Hibernate来写入Blob型数据到Oracle中

Oracle的Blob字段比较特殊,他比long字段的性能要好很多,可以用来保存例如图片之类的二进制数据。 写入Blob字段和写入其它类型字段的方式非常不同,因为Blob自身有一个cursor,你必须使用cursor对blob进行操作,因而你在写入Blob之前,必须获得cursor才能进行写入,那么如何获得Blob的cursor呢? 这需要你先插入一个empty的blob,这将创建一个blob的c

lijihuai1978的专栏 596

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

上一篇: 在osgi bundle中访问osgi container之外的传统服务
下一篇: hibernate 对于blob的操作
tkxing
博客等级 码龄19年 1粉丝 57原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值