转自:http://www.weste.net/2004/11-3/12250047377.html
http://bbs.csdn.net/topics/370120599
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) {} } } } |
http://wenwen.soso.com/z/q151212357.htm
满意答案
мǒ傀衶dě� 3级 2009-08-22
jsp - 上传图片到数据库中 方法如下:
第一步:建立数据库
create table test_img(id number(4),name varchar(20),img long raw);
第二步:(NewImg.html)
<html><head><title>添加图片</title></head>
<body>
添加图片<br>
<form method="post" action="insertNews.jsp">
图像ID:<input name="id" size="10">
<br>
选择图像:<input type="file" name="image">
<br>
<input type="submit" value="上传" name="submit" size="25">
<input type="reset" value="清除" name="clear" size="25">
<br>
</form>
</body></html>
第三步:插入数据库(InsertImg.jsp)
<%@ page language="java"%>
<%@ page contentType="text/html;charset=gb2312" %>
<%@ page import="java.util.*" %>
<%@ page import="java.sql.*"%>
<%@ page import="java.text.*"%>
<%@ page import="java.io.*"%>
<%
Class.forName("com.microsoft.jdbc.sqlserver.SQLServerDriver"); //com.microsoft.jdbc.sqlserver.SQLserveDriver
String url="jdbc:oracle:thin:@lubin:1521:b2bdb"; //jdbc:microsoft:sqlserver://127.0.0.1:1433; jdbc:microsoft.sqlserver://127.0.0.1:1433
Connection con=DriverManager.getConnection(url,"demo","demo");
//插入数据库
String sql="insert into test_img values (?,?,?)";
//获取传值ID
String id=request.getParameter("id");
//获取image的路径
String kk=request.getParameter("image");
//转换成file格式
File filename=new File(kk);
//将文件的长度读出,并转换成Long型
long l1=filename.length();
int l2=(int)l1;
//以流的格式赋值
FileInputStream fis=new FileInputStream(filename);
PreparedStatement ps =con.prepareStatement(sql);
ps.setString(1,id);
ps.setString(2,filename.getName());
ps.setBinaryStream(3,fis,l2);
//ps.setBinaryStream(3,fis,fis.available());
ps.executeUpdate();
//ps.execute();
ps.close();
fis.close();
out.println("ok!!!");
%>
第四步:显示图片(ShowImg.jsp)
<%@ page language="java" import="java.sql.*"%>
<%@ page import="java.io.*"%>
<%@ page contentType="text/html;charset=gb2312"%>
<%
Class.forName("oracle.jdbc.driver.OracleDriver");
String url="jdbc:oracle:thin:@lubin:1521:b2bdb";
String image_id = (String) request.getParameter("ID");
Connection con=DriverManager.getConnection(url,"demo","demo");
PreparedStatement sql=con.prepareStatement("select * from test_img WHERE id = " + image_id);
ResultSet rs = sql.executeQuery();
rs.next();
//输入img字段内容到in
InputStream in = rs.getBinaryStream("img");
//以下可是任何处理,比如向页面输出:
response.reset();
response.setContentType("image/jpeg");
byte[] b = new byte[1024];
int len;
while((len=in.read(b)) >0)
response.getOutputStream().write(b,0,len);
in.close();
rs.close();
%>
完成该代码的调用必须先建立picture数据库和picture表,如下:
create database picture;
create table picture
(
id int not null auto_increment,
picture longblob,
primary key(id)
);
图片上传到数据库JavaBean的代码如下:
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% UploadToMySql.java %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
import java.sql.*;
import java.io.*;
import java.lang.*;
import java.awt.*;
public class UploadToMySql
{
String strDriver="org.gjt.mm.mysql.Driver";
String strConn="jdbc:mysql://localhost/picture?user=root&password="; //使用时请根据数据库的设 //置做相应的修改。picture为数据库名称。
private Connection conn = null;
private Statement stmt = null;
ResultSet rs = null;
public UploadToMySql()
{
//连接MySql_jdbc驱动程序
try {
Class.forName(strDriver).newInstance();
conn = DriverManager.getConnection(strConn);
}
catch (Exception E)
{
System.err.println("不能连接MySql数据库!");
}
}
//图片写入数据库函数
//sql 为数据库的SQL语句
//filename 为包含完整路径的文件名
//返回结果为字符型,True为成功,False为失败
public boolean WriteInMySql(String sql, String filename)
{
boolean writeReturn = false;
try
{
//定义文件流对象fileStream
FileInputStream fileInStream = null;
PreparedStatement insert;
int bytes = 0;
insert = conn.prepareStatement(sql);
if(filename != null && !filename.equals("") && sql != null && !sql.equals(""))
{
try
{
fileInStream= new FileInputStream(filename);
//available()方法返回int型,就是能够被读出的文件字节数。
bytes = fileInStream.available();
//在preparedStatement对象执行之前,参数?必须被设置好,否则报错。
//该任务由方法setXXX完成。XXX是参数适当的类型,根据数据库定义的字段类型来设置。
//参数的位置由SQl语句的序叙决定。用setBinaryStream来设置文件流的参数。
insert.setBinaryStream(1,fileInStream,bytes);
insert.executeUpdate();
writeReturn = true;
}
catch(Exception e)
{
System.err.println("数据插入失败: " + e.toString());
}
}
try
{
insert.close();
fileInStream.close();
}
catch(Exception e)
{
System.err.println("不能关闭文件流和数据库对象: " + e.toString());
}
}
catch(Exception e)
{
System.err.println("数据库连接错误: " + e.toString());
}
return writeReturn;
}
//图片从数据库读出函数
//sql 为数据库的SQL语句
//返回 暂时将图片写成文件形式,文件名为c:/temppic.bmp
public String ReadFromMySql(String sql)
{
String filepath = "C:/temppic.bmp";
PreparedStatement insert;
Statement query;
FileOutputStream fileOutStream = null;
int bytes = 0;
try
{
query = conn.createStatement();
ResultSet rs = query.executeQuery(sql);
if(rs.next())
{
//读出流用getBinaryStream()方法。
InputStream inStream = rs.getBinaryStream(1);
//图片的有效长度。
int size = inStream.available();
byte[] pictureData = new byte[size];
//read(byte[] b):读取输入流的数据到指定的数组。只是文件的有效部分。
inStream.read(pictureData);
try
{
//将图片文件输出到指定目录。
fileOutStream = new FileOutputStream(filepath);
//写入数据。
fileOutStream.write(pictureData);
}
catch(Exception e)
{
System.err.println("图片文件读出错误: " + e.toString());
}
}
}
catch(Exception e)
{
System.err.println("数据库操作失败: " + e.toString());
}
try
{
fileOutStream.close();
}
catch(Exception e)
{
System.err.println("文件输出流关闭失败: " + e.toString());
}
return filepath;
}
}
common-fileupload是jakarta项目组开发的一个功能很强大的上传文件组件
下面先介绍上传文件到服务器(多文件上传):
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;
import java.util.*;
import java.util.regex.*;
import org.apache.commons.fileupload.*;
public class upload extends HttpServlet {
private static final String CONTENT_TYPE = "text/html; charset=GB2312";
//Process the HTTP Post request
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType(CONTENT_TYPE);
PrintWriter out=response.getWriter();
try {
DiskFileUpload fu = new DiskFileUpload();
// 设置允许用户上传文件大小,单位:字节,这里设为2m
fu.setSizeMax(2*1024*1024);
// 设置最多只允许在内存中存储的数据,单位:字节
fu.setSizeThreshold(4096);
// 设置一旦文件大小超过getSizeThreshold()的值时数据存放在硬盘的目录
fu.setRepositoryPath("c:\\windows\\temp");
//开始读取上传信息
List fileItems = fu.parseRequest(request);
// 依次处理每个上传的文件
Iterator iter = fileItems.iterator();
//正则匹配,过滤路径取文件名
String regExp=".+\\\\(.+)$";
//过滤掉的文件类型
String[] errorType={".exe",".com",".cgi",".asp"};
Pattern p = Pattern.compile(regExp);
while (iter.hasNext()) {
FileItem item = (FileItem)iter.next();
//忽略其他不是文件域的所有表单信息
if (!item.isFormField()) {
String name = item.getName();
long size = item.getSize();
if((name==null||name.equals("")) && size==0)
continue;
Matcher m = p.matcher(name);
boolean result = m.find();
if (result){
for (int temp=0;temp<errorType.length;temp++){
if (m.group(1).endsWith(errorType[temp])){
throw new IOException(name+": wrong type");
}
}
try{
//保存上传的文件到指定的目录
//在下文中上传文件至数据库时,将对这里改写
item.write(new File("d:\\" + m.group(1)));
out.print(name+" "+size+"<br>");
}
catch(Exception e){
out.println(e);
}
}
else
{
throw new IOException("fail to upload");
}
}
}
}
catch (IOException e){
out.println(e);
}
catch (FileUploadException e){
out.println(e);
}
}
}
下面是个html的上传页面:
<h1>文件上传演示</h1>
<form name="uploadform" method="POST" action="/upload" ENCTYPE="multipart/form-data">
<table border="1" width="450" cellpadding="4" cellspacing="2" bordercolor="#9BD7FF">
<tr><td width="100%" colspan="2">
文件1:<input name="x" size="40" type="file">
</td></tr>
<tr><td width="100%" colspan="2">
文件2:<input name="y" size="40" type="file">
</td></tr>
<tr><td width="100%" colspan="2">
文件3:<input name="z" size="40" type="file">
</td></tr>
</table>
<br/><br/>
<table>
<tr><td align="center"><input name="upload" type="submit" value="开始上传"/></td></tr>
</table>
</form>
现在介绍上传文件到服务器,下面只写出相关代码:
以sql2000为例,表结构如下:
字段名:name filecode
类型: varchar image
数据库插入代码为:PreparedStatement pstmt=conn.prepareStatement("insert into test values(?,?)");
代码如下:
。。。。。。
try{
//item.write(new File("d:\\" + m.group(1)));//这段代码如果不去掉,将一同写入到服务器中
int byteread=0;
InputStream inStream=item.getInputStream(); //读取输入流,也就是上传的文件内容
pstmt.setString(1,m.group(1));
pstmt.setBinaryStream(2,inStream,(int)size);
pstmt.executeUpdate();
inStream.close();
out.println(name+" "+size+"<br>");
}
这样就实现了上传文件至数据库
==========================================================================
下面代码是在ORACRE中存储任何文件!!
字段类型为long row,看你是否可以用上!!!
其中中文路径的问题已经解决!
package aaa;
//加入相应的包
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;
import java.util.*;
import java.sql.*;
import java.sql.PreparedStatement;
import java.sql.Connection;
public class in extends HttpServlet {
private static final String CONTENT_TYPE = "text/html; charset=GBK";
//Initialize global variables
public void init() throws ServletException {
}
//Process the HTTP Get request
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType(CONTENT_TYPE);
PrintWriter out = response.getWriter();
conn conn=new conn();
//转换字符串的编码格式
request.setCharacterEncoding("GBK");
//conn.Getconnect().
//从上一页面获取相应插入的信息
String XMDM=request.getParameter("XMDM");
String ZLLX=request.getParameter("ZLLX");
String SBRQ=request.getParameter("SBRQ");
String ZLNR=request.getParameter("ZLNR");
//将得到的文件路径转换成为相应的文件格式!
java.io.File file=new java.io.File(ZLNR);
//取得文件的长度!!
long l1=file.length();
int s=(int)l1;
String ZLCD=String.valueOf(s);
//取得文件名及后缀!!
String ZLHZ=file.getName() ;
//将文件转换成为数据流!!
FileInputStream str=new FileInputStream(ZLNR);
// String sql="insert into AAA(A,B) values(?,?)";
String sql="insert into GZ_XGZL(XMDM,ZLLX,ZLMC,SBRQ,ZLNR,ZLCD) values(?,?,?,?,?,?)";
//向数据库读流!!连接数据库插入数据。
try {
PreparedStatement pstmt = conn.Getconnect().prepareStatement(sql);
pstmt.setString(1,XMDM);
pstmt.setString(2,ZLLX);
pstmt.setString(3,ZLHZ);
pstmt.setString(4,SBRQ);
pstmt.setBinaryStream(5,str,s);
pstmt.setString(6,ZLCD);
pstmt.execute();
}
catch (SQLException ex) {
}
response.sendRedirect("update.jsp");
}}
你这是复制别人的啊
满意答案
hello疯子 6级 2009-08-21
%@ page language="java"%>
<%@ page contentType="text/html;charset=gb2312" %>
<%@ page import="java.util.*" %>
<%@ page import="java.sql.*"%>
<%@ page import="java.text.*"%>
<%@ page import="java.io.*"%>
<%
Class.forName("com.microsoft.jdbc.sqlserver.SQLServerDriver"); //com.microsoft.jdbc.sqlserver.SQLserveDriver
String url="jdbc:oracle:thin:@lubin:1521:b2bdb"; //jdbc:microsoft:sqlserver://127.0.0.1:1433; jdbc:microsoft.sqlserver://127.0.0.1:1433
Connection con=DriverManager.getConnection(url,"demo","demo");
String sql="insert into test_img values (?,?,?)";
String id=request.getParameter("id");
String kk=request.getParameter("image");
File filename=new File(kk);
long l1=filename.length();
int l2=(int)l1;
FileInputStream fis=new FileInputStream(filename);
PreparedStatement ps =con.prepareStatement(sql);
ps.setString(1,id);
ps.setString(2,filename.getName());
ps.setBinaryStream(3,fis,l2);
//ps.setBinaryStream(3,fis,fis.available());
ps.executeUpdate();
//ps.execute();
ps.close();
fis.close();
out.println("ok!!!");
%>
显示图片
<%@ page language="java" import="java.sql.*"%>
<%@ page import="java.io.*"%>
<%@ page contentType="text/html;charset=gb2312"%>
<%
Class.forName("oracle.jdbc.driver.OracleDriver");
String url="jdbc:oracle:thin:@lubin:1521:b2bdb";
String image_id = (String) request.getParameter("ID");
Connection con=DriverManager.getConnection(url,"demo","demo");
PreparedStatement sql=con.prepareStatement("select * from test_img WHERE id = " + image_id);
ResultSet rs = sql.executeQuery();
rs.next();
InputStream in = rs.getBinaryStream("img");
response.reset();
response.setContentType("image/jpeg");
byte[] b = new byte[1024];
int len;
while((len=in.read(b)) >0)
response.getOutputStream().write(b,0,len);
in.close();
rs.close();
javabean上传实例
package com.brainysoftware.web;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.ServletInputStream;
import java.util.Dictionary;
import java.util.Hashtable;
import java.io.PrintWriter;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
public class FileUploadBean {
private String savePath, filepath, filename, contentType;
private Dictionary fields;
public String getFilename() {
return filename;
}
public String getFilepath() {
return filepath;
}
public void setSavePath(String savePath) {
this.savePath = savePath;
}
public String getContentType() {
return contentType;
}
public String getFieldValue(String fieldName) {
if (fields == null || fieldName == null)
return null;
return (String) fields.get(fieldName);
}
private void setFilename(String s) {
if (s==null)
return;
int pos = s.indexOf("filename=\"");
if (pos != -1) {
filepath = s.substring(pos+10, s.length()-1);
// Windows浏览器发送完整的文件路径和名字
// 但Linux/Unix和Mac浏览器只发送文件名字
pos = filepath.lastIndexOf("\\");
if (pos != -1)
filename = filepath.substring(pos + 1);
else
filename = filepath;
}
}
private void setContentType(String s) {
if (s==null)
return;
int pos = s.indexOf(": ");
if (pos != -1)
contentType = s.substring(pos+2, s.length());
}
public void doUpload(HttpServletRequest request) throws IOException {
ServletInputStream in = request.getInputStream();
byte[] line = new byte[128];
int i = in.readLine(line, 0, 128);
if (i < 3)
return;
int boundaryLength = i - 2;
String boundary = new String(line, 0, boundaryLength); //-2丢弃换行字符
fields = new Hashtable();
while (i != -1) {
String newLine = new String(line, 0, i);
if (newLine.startsWith("Content-Disposition: form-data; name=\"")) {
if (newLine.indexOf("filename=\"") != -1) {
setFilename(new String(line, 0, i-2));
if (filename==null)
return;
//文件内容
i = in.readLine(line, 0, 128);
setContentType(new String(line, 0, i-2));
i = in.readLine(line, 0, 128);
//空行
i = in.readLine(line, 0, 128);
newLine = new String(line, 0, i);
PrintWriter pw = new PrintWriter(new BufferedWriter(new
FileWriter((savePath==null? "" : savePath) + filename)));
while (i != -1 && !newLine.startsWith(boundary)) {
// 文件内容的最后一行包含换行字符
// 因此我们必须检查当前行是否是最
// 后一行
i = in.readLine(line, 0, 128);
if ((i==boundaryLength+2 || i==boundaryLength+4)
&& (new String(line, 0, i).startsWith(boundary)))
pw.print(newLine.substring(0, newLine.length()-2));
else
pw.print(newLine);
newLine = new String(line, 0, i);
}
pw.close();
}
else {
// 普通表单输入元素
// 获取输入元素名字
int pos = newLine.indexOf("name=\"");
String fieldName = newLine.substring(pos+6, newLine.length()-3);
i = in.readLine(line, 0, 128);
i = in.readLine(line, 0, 128);
newLine = new String(line, 0, i);
StringBuffer fieldValue = new StringBuffer(128);
while (i != -1 && !newLine.startsWith(boundary)) {
// 最后一行包含换行字符
// 因此我们必须检查当前行是否是最后一行
i = in.readLine(line, 0, 128);
if ((i==boundaryLength+2 || i==boundaryLength+4)
&& (new String(line, 0, i).startsWith(boundary)))
fieldValue.append(newLine.substring(0, newLine.length()-2));
else
fieldValue.append(newLine);
newLine = new String(line, 0, i);
}
fields.put(fieldName, fieldValue.toString());
}
}
i = in.readLine(line, 0, 128);
}
}
}