无法将图像保存为blob到sqlite

时间:2011-05-22 19:19:10

标签: java sqlite

我使用的是SQLite,我无法将图像保存到数据库中。 这是我的代码:

File file = new File(url);
  try {
    fis = new FileInputStream(file);
  } catch (FileNotFoundException e) {}
fileLenght = (int) file.length();

stat.executeUpdate("create table "+tableName+" (id int,name String ,image Blob, features String);");
prep = conn.prepareStatement("insert into "+tableName+" values (?, ?, ?, ?);");
prep.setBinaryStream(3, fis, fileLenght);

这是我得到的错误:

java.sql.SQLException: not implemented by SQLite JDBC driver
  at org.sqlite.Unused.unused(Unused.java:29)
  at org.sqlite.Unused.setBinaryStream(Unused.java:58)

我正在使用以下jar:sqlitejdbc-v056.jar。

有什么想法吗? 感谢

5 个答案:

答案 0 :(得分:14)

您正在使用的SQLite JDBC实现未实现setBinaryStream(因此SQLite JDBC驱动程序错误消息未实现准确的)。

您需要改为使用setBytes方法。

答案 1 :(得分:9)

您可以非常轻松地将图像插入数据库,说SQLite请参阅以下代码。 我确实使用了DBase Connection的属性文件,你可以放在任何地方。

public class JDBCSqliteConn
{
    public static void main(String args[]) throws FileNotFoundException, IOException
    {
        Connection connection = null;
        //ResultSet resultSet = null;
        PreparedStatement ps = null;
        String file = "C:\\Fingerprint\\histoImg_med.png";
        Properties prop = new Properties();
        int s = 0;
        byte[] person_image = null;
        File image = new File(file);
        FileInputStream fis = new FileInputStream(image);
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        byte[] buf = new byte[1024];

        try {
            for (int readNum; (readNum = fis.read(buf)) != -1;)
            {
                bos.write(buf, 0, readNum);
                //no doubt here is 0
                /*Writes len bytes from the specified byte array starting at offset
                off to this byte array output stream.*/
                System.out.println("read " + readNum + " bytes,");
            }
        } catch (IOException ex) {
            System.err.println(ex.getMessage());
        }
        person_image = bos.toByteArray();

        try {
            prop.load(new FileInputStream("C:\\dbconfig.properties"));  
            Class.forName(prop.getProperty("driver"));
            connection = DriverManager.getConnection(prop.getProperty("url"));

            ps = connection.prepareStatement("INSERT INTO epmc_tbl_test_img (hhld_photo) VALUES (?)");
            ps.setBytes(1, person_image);
            s = ps.executeUpdate();
            if (s > 0)
            {
                System.out.println("Image Uploaded");
            }
            ps.close();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                ps.close();
                connection.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

背后的逻辑是将图像转换为bytearray然后存储到数据库,SQLite接受Image类型BLOB的字节数组

这是我的dbconfig.properties文件

driver = org.sqlite.JDBC
url = jdbc:sqlite:C:\\Ronald\\Personal\\epmc\\JavaJ2EE\\EPMC.db

尝试使用此代码。

答案 2 :(得分:2)

要在Hibernate中使用它,您必须使用正确的UserType:

public class PersistentFileAsBlob implements EnhancedUserType, Serializable {

    public static final PersistentFileAsBlob INSTANCE = new PersistentFileAsBlob();

    private static final int[] SQL_TYPES = new int[] { Types.BLOB };

    @Override
    public int[] sqlTypes() {
        return SQL_TYPES;
    }

    @Override
    public Class<?> returnedClass() {
        return File.class;
    }

    @Override
    public boolean equals(Object x, Object y) throws HibernateException {
        if (x == y) {
            return true;
        }
        if (x == null || y == null) {
            return false;
        }
        File dtx = (File) x;
        File dty = (File) y;
        return dtx.equals(dty);
    }

    @Override
    public int hashCode(Object x) throws HibernateException {
        return x.hashCode();
    }

    @Override
    public Object nullSafeGet(ResultSet rs, String[] names, Object owner)
            throws HibernateException, SQLException {
        if (owner == null) {
            return null;
        }

        FileOutputStream fos = null;
        GzipCompressorInputStream cis = null;
        try {
            File file = File.createTempFile(String.valueOf(owner.hashCode()),
                    "");
            byte[] bytes = rs.getBytes(names[0]);
            System.out.println(bytes.length);
            fos = new FileOutputStream(file);
            cis = new GzipCompressorInputStream(new BufferedInputStream(
                    new ByteArrayInputStream(bytes)));
            int n = 0;
            final byte[] buffer = new byte[1024];
            while (-1 != (n = cis.read(buffer))) {
                fos.write(buffer, 0, n);
            }
            fos.close();
            return file;
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        } finally {
            if (fos != null)
                try {
                    fos.close();
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            if (cis != null)
                try {
                    cis.close();
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
        }
    }

    @Override
    public void nullSafeSet(PreparedStatement st, Object value, int index)
            throws HibernateException, SQLException {
        if (value == null) {
            StandardBasicTypes.BINARY.nullSafeSet(st, null, index);
            return;
        }

        File file = (File) value;

        FileInputStream fis = null;
        ByteArrayOutputStream bos = null;
        GzipCompressorOutputStream cos = null;
        try {
            fis = new FileInputStream(file);
            bos = new ByteArrayOutputStream();
            cos = new GzipCompressorOutputStream(new BufferedOutputStream(bos));
            int n = 0;
            final byte[] buffer = new byte[1024];
            while (-1 != (n = fis.read(buffer))) {
                cos.write(buffer, 0, n);
            }
            cos.close();
            StandardBasicTypes.BINARY.nullSafeSet(st, bos.toByteArray(), index);
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        } finally {
            if (fis != null)
                try {
                    fis.close();
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            if (cos != null)
                try {
                    cos.close();
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
        }
    }

    @Override
    public Object deepCopy(Object value) throws HibernateException {
        return value;
    }

    @Override
    public boolean isMutable() {
        return false;
    }

    @Override
    public Serializable disassemble(Object value) throws HibernateException {
        return (Serializable) value;
    }

    @Override
    public Object assemble(Serializable cached, Object owner)
            throws HibernateException {
        return cached;
    }

    @Override
    public Object replace(Object original, Object target, Object owner)
            throws HibernateException {
        return original;
    }

    @Override
    public String objectToSQLString(Object value) {
        throw new UnsupportedOperationException();
    }

    @Override
    public String toXMLString(Object value) {
        return value.toString();
    }

    @Override
    public Object fromXMLString(String xmlValue) {
        return new File(xmlValue);
    }

}

然后您注释键入,请参阅此UserType:

@Entity
public class Mensagem {

    @Column(nullable = false)
    @Type(type = "package.to.class.PersistentFileAsBlob")
    private File file;

}

正如您所看到的,我在保存和解压缩之前压缩数据,然后再进行检索。看看this site

答案 3 :(得分:1)

submitted包含setBinaryStream实现的Xerial补丁。

使用setBytes对我来说不是一个选项,因为我使用hibernate来访问数据库。

diff -r 144ade82d1fe -r 5a141e1b82f0 src/main/java/org/sqlite/PrepStmt.java
--- a/src/main/java/org/sqlite/PrepStmt.java        Thu Jun 09 17:15:36 2011 +0900
+++ b/src/main/java/org/sqlite/PrepStmt.java        Wed Oct 26 11:02:15 2011 -0700
@@ -16,7 +16,9 @@

 package org.sqlite;

+import java.io.ByteArrayOutputStream;
 import java.io.IOException;
+import java.io.InputStream;
 import java.io.Reader;
 import java.sql.Date;
 import java.sql.ParameterMetaData;
@@ -254,6 +256,38 @@
         batch(pos, value);
     }   

+    @Override
+    public void setBinaryStream(int pos, InputStream istream, int length) throws SQLException
+    {
+      ByteArrayOutputStream baos = new ByteArrayOutputStream();
+      try 
+      {
+        int bval = 0;
+   
+        while ((bval = istream.read()) != -1)
+        {   
+          baos.write(bval);
+        }   
+        baos.flush();
+        setBytes(pos, baos.toByteArray());
+      }   
+      catch (IOException e)
+      {
+        throw new SQLException("Cannot read from binary stream, exception message: " + e.getMessage());
+      }
+      finally
+      {
+        try 
+        {   
+          baos.close();
+        }   
+        catch (IOException e)
+        {   
+          throw new SQLException("Can't close stream");
+        }   
+      }
+    }
+   
     public void setCharacterStream(int pos, Reader reader, int length) throws SQLException {
         try {
             // copy chars from reader to StringBuffer

答案 4 :(得分:0)

您似乎没有绑定语句中的所有四个参数。