虽然说现在大部分公司都把文件存放在一个单独的文件服务器上,在数据库中存的是图片的地址,但是还有一些比较落后的公司直接把图片放在数据库中,这种方式比较占用数据库容量,而且不方便检索,前台也不好处理,但是我就遇到了这样一个需求,将本地文件导入到Oracle数据库中。
1、添加依赖
com.alibaba
druid
1.1.22
com.oracle
ojdbc6
11.2.0.2.0
我创建的是一个普通的maven项目。由于只需要和数据库交互,所以只用添加数据库驱动就可以了,我们开发用的是Oracle数据库,所以用的是Oracle驱动,如果是MySQL数据库就需要使用MYSQL驱动。我还添加了druid的依赖,其实是没有必要的。
2、配置文件
jdbc.properties
driver=oracle.jdbc.OracleDriver
url=jdbc:oracle:thin:@192.168.6.222:1521:sid
userName=test
password=test
这个配置文件保存jdbc连接的配置信息,放在resources目录下。
3、工具类
import com.alibaba.druid.pool.DruidDataSource;
import java.io.InputStream;
import java.sql.*;
import java.util.Properties;
public class JDBCUtils {
private static DruidDataSource dataSource = new DruidDataSource();
static{
try {
//从本地文件中读取配置信息
Properties properties = new Properties();
//获取当前类的根路径 , 读取配置文件
InputStream is = JDBCUtils.class.getClassLoader().getResourceAsStream("jdbc.properties");
properties.load(is);
dataSource.setDriverClassName(properties.getProperty("driver"));
dataSource.setUrl(properties.getProperty("url"));
dataSource.setUsername(properties.getProperty("userName"));
dataSource.setPassword(properties.getProperty("password"));
dataSource.setMaxActive(150);
} catch (Exception e) {
e.printStackTrace();
}
}
public static Connection getConnection() {
Connection cn = null;
try {
cn = dataSource.getConnection();
} catch (SQLException e) {
e.printStackTrace();
}
return cn;
}
public static void close(Statement st, Connection cn){
close(null,st,cn);
}
public static void close(ResultSet rs, Statement st, Connection cn){
//关闭连接
if(rs!=null){
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(st!=null){
try {
st.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(cn!=null){
try {
cn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
JDBCUtils工具类用于读取配置文件、获取连接、关闭连接。
4、主类
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.PrintStream;
import java.sql.*;
/**
* @author huwen
*/
public class ImportImage {
private Connection conn;
/**
* 向表中插入图片
*
* @param path 图片所在的路径
* @return 整形 判断成功或失败
*/
public int insertImage(File path) throws Exception {
int i = 0;
Statement st = null;
ResultSet rs = null;
conn=JDBCUtils.getConnection();
//设置数据库为不自动提交,必须的一步
conn.setAutoCommit(false);
//先插入一个空对象,这里我调用了Empty_BLOB()函数
st = conn.createStatement();
//先插入一个空对象,这里我调用了Empty_BLOB()函数
String paperNo = path.getName().split("\\.")[0];
String insertSql = "insert into TF_F_CARDPARKPHOTO_SZ_TMP (parpno,picture,operatetime) values ('"+paperNo+"',Empty_BLOB(),sysdate)";
i = st.executeUpdate(insertSql);
//以行的方式锁定
String selectSql = "select picture from TF_F_CARDPARKPHOTO_SZ_TMP where parpno= '"+paperNo+"' for update";
rs = st
.executeQuery(selectSql);
if (rs.next()) {
//得到流
oracle.sql.BLOB blob = (oracle.sql.BLOB) rs.getBlob(1);
//从得到的低级流构造一个高级流
if(blob==null){
System.out.println(paperNo);
}
PrintStream ps = new PrintStream(blob.getBinaryOutputStream());
BufferedInputStream bis = new BufferedInputStream(
new FileInputStream(path));
byte[] buff = new byte[1024];
int n = 0;
//从输入到输出
while ((n = bis.read(buff)) != -1) {
ps.write(buff, 0, n);
}
//清空流的缓存
ps.flush();
//关闭流,注意一定要关
ps.close();
bis.close();
}
conn.commit();
JDBCUtils.close(rs,st,conn);
return i;
}
public static void main(String[] args) throws Exception {
ImportImage test=new ImportImage();
File file = new File("C:\\Users\\huwen\\Documents\\1109");
for (File f : file.listFiles()) {
test.insertImage(f);
}
System.out.println("OK");
}
}
首先要保证表中没有数据,并且有一个字段数据类型为BLOB。这种做法的原理是先向表中插入一个Empty_Blob()函数创建的数据,然后以行的方式锁定读取该字段信息,从磁盘中读取文件写入。中间一定要注意关闭自动提交
,执行完后进行手动提交
。