本人是在ssh框架下所建的工程,在一开始学习BLOB数据的插入和读取的时候遇到蛮多的问题,诸如:java.sql.Blob无法转换成oracle.sql.BLOB类型的问题(但使用JDBC时好像不存在类型转换的问题)、输出流输入流的方法的使用、映射表的定义、数据类型的匹配的等问题。
这是我的工程目录,主要是下面的四个文件
这是我的Cat类:
public class Cat {
private Integer id;
private String name;
private int sex;
private float weight;
private Blob image;
public Cat() {
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getSex() {
return sex;
}
public void setSex(int 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;
}
}
这个是我的PetPO.hbm.xml文件的映射表:
<class name="cn.com.starit.beans.Cat" table="sun.Cat">
<id name="id" column="c_id" type="java.lang.Integer" >
<generator class="sequence">
<param name="sequence">sun.ssss</param>
</generator>
</id>
<property name="name" column="c_name" type="java.lang.String"/>
<property name="sex" column="c_sex" type="int"/>
<property name="weight" column="c_weight" type="float"/>
<property name="image" column="c_image" type="blob" />
</class>
先来说一下使用JDBC写入图片吧:主要由两段代码
插入图片的代码:
当我使用JDBC的时候,需要将id也要set进去,id又是主键,因此插入的时候不要忘了有重复。另外:网上说的要先将Blob字段置为空,然后再插入图片进行更新,实现插入。但本人在使用mysql数据库中,是直接赋值没有置空值,如果有兴趣的话可以试试。。。
public class testJdbcCat {
public static void main(String[] args) throws SQLException, IOException {
DriverManager.registerDriver(new oracle.jdbc.driver.OracleDriver());
Connection conn = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:orcl1","sun","123456");
conn.setAutoCommit(false);
BLOB blob = null;
PreparedStatement pstmt;
pstmt = conn.prepareStatement("insert into sun.Cat(c_id,c_name,c_sex,c_weight,c_image) values(?,?,?,?,empty_blob())");
pstmt.setString(1,"1");
pstmt.setString(2,"fankai");
pstmt.setInt(3,1);
pstmt.setFloat(4,30);
pstmt.executeUpdate();
pstmt.close();
pstmt = conn.prepareStatement("select c_image from sun.Cat where c_id= ? for update");
pstmt.setString(1,"1");
ResultSet rset = pstmt.executeQuery();
if (rset.next())
blob = (BLOB) rset.getBlob(1);
String fileName = "E:/http_imgloadCANWA7W2.jpg";
File f = new File(fileName);
FileInputStream fin = new FileInputStream(f);
System.out.println("file size = " + fin.available());
pstmt = conn.prepareStatement("update sun.Cat set c_image=? where c_id=?");
OutputStream out = blob.getBinaryOutputStream();
//int count = -1, total = 0;
byte[] data = new byte[(int)fin.available()];
fin.read(data);
out.write(data);
fin.close();
out.close();
pstmt.setBlob(1,blob);
pstmt.setString(2,"1");
pstmt.executeUpdate();
pstmt.close();
conn.commit();
conn.close();
}
}
读取图片的代码:
这里要注意一下:本人是直接从blob中直接获取字节 byte [] buff = blob.getBytes(1,lens); 如果从blob中先获取inputstream,然后将二进制流read到字节数组中的话,可能会有问题。。。
public class JDBCGetCats {
public static void main(String[] args) throws SQLException, IOException {
DriverManager.registerDriver(new oracle.jdbc.driver.OracleDriver());
Connection conn = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:orcl1","sun","123456");
conn.setAutoCommit(false);
Blob blob=null;
PreparedStatement pstmt;
pstmt = conn.prepareStatement("select c_image from sun.Cat where c_id = '232'");
ResultSet rset = pstmt.executeQuery();
if (rset.next())
blob = rset.getBlob(1);
System.out.println(blob.length());
FileOutputStream out= new FileOutputStream("E:/Myoutput.jpg");
int lens=(int)blob.length();
byte [] buff = blob.getBytes(1,lens);
out.write(buff);
out.close();
conn.commit();
conn.close();
}
}
接下来说说Hibernate插入和读取图片的方法吧:
因为用到了hibernate框架,所以本在映射表中对id插入了一个序列确保主键不重复,这个序列是要自己在数据库中自己建,建序列很简单create sequence sun.ssss;就这么一句,呵呵。还有要将image数据设为可以是null
这里值得注意的地方是 SerializableBlob b= (SerializableBlob) c.getImage(); BLOB blob=(BLOB)b.getWrappedBlob(); 它通过一个中间类型进行转换,这样就应该可以使用BLOB的getBinaryOutputStream()方法获取输出流了。具体为什么可以这样,本人也不清楚,不过确实SerializableBlob的getWrappedBlob()这个方法帮了大忙。
public class TestHibernateCat {
public static void main(String[] args) {
Session s = null;
byte[] buffer = new byte[1];
buffer[0] = 1;
try {
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
SessionFactoryImpl sf = (SessionFactoryImpl) ac.getBean("sessionFactory");
s = sf.openSession();
Transaction tx = s.beginTransaction();
Cat c = new Cat();
c.setName("Robbin");
c.setImage(Hibernate.createBlob(buffer));
c.setWeight(20);
c.setSex(1);
s.save(c);
s.flush();
s.refresh(c, LockMode.UPGRADE);
SerializableBlob b= (SerializableBlob) c.getImage();
BLOB blob=(BLOB)b.getWrappedBlob();
//BLOB blob=(BLOB)c.getImage();
OutputStream out = blob.getBinaryOutputStream();
String fileName = "E:/2.jpeg";
File f = new File(fileName);
FileInputStream fin = new FileInputStream(f);
byte[] data = new byte[(int)fin.available()];
fin.read(data);
out.write(data);
fin.close();
out.close();
s.flush();
tx.commit();
} catch (Exception e) {
e.printStackTrace();
System.out.println(e.getMessage());
} finally {
if (s != null)
try {
s.close();
} catch (Exception e) {
e.printStackTrace();
}
}
/*
FileInputStream fis= new FileInputStream("E:/http_imgloadCANWA7W2.jpg");
FileOutputStream fos= new FileOutputStream("E:/Myoutput1.jpg");
int a;
while((a=fis.read())!=-1) {// fis调用方法read()读一字节
fos.write(a);//fos调用write把读入数据写到输出文件
//System.out.println("a="+a);
}
fis.close();
fos.close();*/
}
}
注:上面代码中被注释掉的那一段东西是用来将一个图片文件中放到另一个自己建的文件中。
对于使用Hibernate获取图片,List<Blob> list=DaoServiceProvider.getResInstanceDao().ImageByCatId(232);这句中使用sql/hql语句获取数据时用到了我们公司自己的类,当然hi
bernate有自己的增删改方法也一样可以使用来实现。另外的语句和JDBC使用的差不多。
public class HibernateGetCats {
public static void main(String[] args) throws IOException, SQLException {
List<Blob> list=DaoServiceProvider.getResInstanceDao().ImageByCatId(232);
if(list!=null&&list.size()>0){
Session s = null;
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
SessionFactoryImpl sf = (SessionFactoryImpl) ac.getBean("sessionFactory");
s = sf.openSession();
Transaction tx = s.beginTransaction();
byte [] buff=list.get(0).getBytes(1,(int) list.get(0).length());
FileOutputStream fout=new FileOutputStream("E:/11.jpg");
fout.write(buff);
fout.close();
tx.commit();
s.close();
}
}
}
困了。。。先睡了
,希望能给在这方面遇到的困难的同学们一点帮助。