要将文件直接插入数据库,可以通过使用BLOB和CLOB字段类型来完成:大致是先在数据中插入记录,然后再通过for update 语句将对象查询出来(这里有事务提交问题),最后通过oracle包的BLOB字段获取输出流,将对象写进数据库。
使用Mybatis如下:
1.POJO:
public class FileInfo { private String fileId; //文件二进制流字段,这里要用Object类型,我试了BLOB类型都不行。 private Object fileContent; ... }
2.Service方法:
//先将对象插入
dao.insertFile(fileInfo); //再获取文件二进制流,将文件对象插入数据
fileInfo=dao.getFileById(fileInfo.getFileId()); oracle.sql.BLOB blob = (BLOB) fileInfo.getFileContent(); os = blob.setBinaryStream(0); //这是最新的获取流方法 URL url = new URL(fileInfo.getFileDownloadUrl()); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); is = new BufferedInputStream(conn.getInputStream()); byte[] bytes = new byte[2048]; int len; while ((len = is.read(bytes)) != -1) {
//这里不能直接os.write(bytes),会导致文件损坏 os.write(bytes, 0, len); } os.flush();
3.sql语句:
<insert id="insertFile"> <selectKey keyProperty="fileId" resultType="String" order="BEFORE"> SELECT file_seq.nextval FROM dual </selectKey> INSERT INTO file( file_id, CONTENT, creation_Date ) VALUES ( #{fileId}, empty_blob(), <--用 empty_blob() 函数占位--> sysdate ) </insert> <--在用for update 语句将BLOB字段写入--> <select id="getFileById" resultType="entity.abuteInter.FileInfo"> SELECT * FROM file WHERE file_id=#{fileId} for update </select>
这样基本就OK了,不过一开始出现了一个怪现象,我在一个for循环里插入多个文件,最后一个文件却总是为空。经检查发现,在for update查询语句之后没有提交事务,前面的数据因为后面会继续执行insert操作,所以事务自动提交了,而最后一条记录结束就没办法了。一般网上很多例子都是用Connection 打开连接,然后用提交事务,但是我用mybatis没法,只得再执行一个方法,sql:
<select id="commit"> COMMIT </select>
这是oracle提交事务的sql语句。用Connection.commit方法是对当前连接的事务操作,也就是对其他的连接事务无效,但是这个语句应该是数据库整体事务。