2011-05-22 2 views
8

J'utilise SQLite et je ne peux pas enregistrer une image dans la base de données. Ceci est mon code:impossible d'enregistrer l'image en tant que blob sur 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); 

Ceci est l'erreur que je reçois:

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) 

J'utilise le pot suivant: sqlitejdbc-v056.jar.

Des idées? Merci

Répondre

14

La mise en œuvre SQLite JDBC que vous utilisez ne met pas en œuvre setBinaryStream (d'où le précise pas mis en œuvre par le pilote JDBC SQLite message d'erreur).

Vous aurez besoin d'utiliser la méthode à la place setBytes.

+0

j'ai remplacé setBinaryStream avec setBytes et cela fonctionne .... merci :) – Mara

+0

Golden: totalement ne m'attendais pas à ce que cela fonctionne, mais heureux il l'a fait :-) – Femi

+0

Surpris il isn un pilote JDBC plus récent/complet que celui-ci – Femi

0

Il semble que vous n'êtes pas liez à tous les quatre paramètres dans votre déclaration.

+0

Je l'ai fait dans mon code, mais je ne l'ai pas écrit ici parce que je pense que ce n'est pas pertinent. quand j'essaie de sauver l'image quelque chose va mal – Mara

9

Vous pouvez insérer une image très facilement dans la base de données, par exemple SQLite voir mon code suivant. J'ai utilisé un fichier de propriétés pour DBase Connection que vous pouvez placer n'importe où.

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(); 
      } 
     } 
    } 
} 

La logique am convertissait derrière les images pour byteArray puis stocker la base de données, SQLite accepte tableau d'octets pour le type d'image blob

et voici mon dbconfig.properties fichier

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

Essayez d'utiliser ce code.

1

Demandez submitted un patch pour XERIAL contenant la mise en œuvre de setBinaryStream.

Utilisation setBytes n'a pas été une option pour moi, comme je me sers en veille prolongée pour accéder à la base de données.

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 
2

Pour l'utiliser avec Hibernate, vous devez utiliser un UserType approprié:

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); 
    } 

} 

Ensuite, vous annoter vous tapez, en se référant à cette UserType:

@Entity 
public class Mensagem { 

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

} 

Comme vous pouvez le voir je m compression des données avant l'enregistrement et la décompression avant la récupération. Jetez un oeil à this site.

Questions connexes