2012-05-08 25 views
0

Hy!sqliteデータベースからBLOBデータを読み込む - > jpa(hibernate)

私はJSF、春、JPA(休止状態)を使用しています私はSQLiteのデータベースからBLOBデータを読みたいが、私はいつもこのエラーメッセージ

08.05.2012 15:06:28 org.hibernate.engine.jdbc.spi.SqlExceptionHelper logExceptions 
WARN: SQL Error: 0, SQLState: null 
08.05.2012 15:06:28 org.hibernate.engine.jdbc.spi.SqlExceptionHelper logExceptions 
ERROR: not implemented by SQLite JDBC driver 

を取得します。

Sqliteをテーブルの構造

CREATE TABLE LOGO ('logo_id' INTEGER PRIMARY KEY NOT NULL, 'logo_data' BLOB) 

コード1行を読み取るため:

public void loadLogo() { 
    try { 
     Query query = entityManager.createNativeQuery("SELECT * FROM logo"); 
     Vector v = (Vector) query.getSingleResult(); 
     byte[] blobData = (byte[]) v.elementAt(1); 
    } catch (Exception e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } 
} 

Sqliteを方言:

public class SQLiteDialect extends Dialect implements Serializable { 

private static final long serialVersionUID = 1L; 

public SQLiteDialect() { 
    registerColumnType(Types.BIT, "integer"); 
    registerColumnType(Types.TINYINT, "tinyint"); 
    registerColumnType(Types.SMALLINT, "smallint"); 
    registerColumnType(Types.INTEGER, "integer"); 
    registerColumnType(Types.BIGINT, "bigint"); 
    registerColumnType(Types.FLOAT, "float"); 
    registerColumnType(Types.REAL, "real"); 
    registerColumnType(Types.DOUBLE, "double"); 
    registerColumnType(Types.NUMERIC, "numeric"); 
    registerColumnType(Types.DECIMAL, "decimal"); 
    registerColumnType(Types.CHAR, "char"); 
    registerColumnType(Types.VARCHAR, "varchar"); 
    registerColumnType(Types.LONGVARCHAR, "longvarchar"); 
    registerColumnType(Types.DATE, "date"); 
    registerColumnType(Types.TIME, "time"); 
    registerColumnType(Types.TIMESTAMP, "timestamp"); 
    registerColumnType(Types.BINARY, "blob"); 
    registerColumnType(Types.VARBINARY, "blob"); 
    registerColumnType(Types.LONGVARBINARY, "blob"); 
    registerColumnType(Types.NULL, "null"); 
    registerColumnType(Types.BLOB, "blob"); 
    registerColumnType(Types.CLOB, "clob"); 
    registerColumnType(Types.BOOLEAN, "integer"); 

    registerFunction("concat", new VarArgsSQLFunction(
      StandardBasicTypes.STRING, "", "||", "")); 
    registerFunction("mod", new SQLFunctionTemplate(
      StandardBasicTypes.INTEGER, "?1 % ?2")); 
    registerFunction("substr", new StandardSQLFunction("substr", 
      StandardBasicTypes.STRING)); 
    registerFunction("substring", new StandardSQLFunction("substr", 
      StandardBasicTypes.STRING)); 
} 

public boolean supportsIdentityColumns() { 
    return true; 
} 

/* 
* public boolean supportsInsertSelectIdentity() { return true; // As 
* specify in NHibernate dialect } 
*/ 

public boolean hasDataTypeInIdentityColumn() { 
    return false; // As specify in NHibernate dialect 
} 

/* 
* public String appendIdentitySelectToInsert(String insertString) { return 
* new StringBuffer(insertString.length()+30). // As specify in NHibernate 
* dialect append(insertString). 
* append("; ").append(getIdentitySelectString()). toString(); } 
*/ 

public String getIdentityColumnString() { 
    // return "integer primary key autoincrement"; 
    return "integer"; 
} 

public String getIdentitySelectString() { 
    return "select last_insert_rowid()"; 
} 

public boolean supportsLimit() { 
    return true; 
} 

protected String getLimitString(String query, boolean hasOffset) { 
    return new StringBuffer(query.length() + 20).append(query) 
      .append(hasOffset ? " limit ? offset ?" : " limit ?") 
      .toString(); 
} 

public boolean supportsTemporaryTables() { 
    return true; 
} 

public String getCreateTemporaryTableString() { 
    return "create temporary table if not exists"; 
} 

public boolean dropTemporaryTableAfterUse() { 
    return false; 
} 

public boolean supportsCurrentTimestampSelection() { 
    return true; 
} 

public boolean isCurrentTimestampSelectStringCallable() { 
    return false; 
} 

public String getCurrentTimestampSelectString() { 
    return "select current_timestamp"; 
} 

public boolean supportsUnionAll() { 
    return true; 
} 

public boolean hasAlterTable() { 
    return false; // As specify in NHibernate dialect 
} 

public boolean dropConstraints() { 
    return false; 
} 

public String getAddColumnString() { 
    return "add column"; 
} 

public String getForUpdateString() { 
    return ""; 
} 

public boolean supportsOuterJoinForUpdate() { 
    return false; 
} 

public String getDropForeignKeyString() { 
    throw new UnsupportedOperationException(
      "No drop foreign key syntax supported by SQLiteDialect"); 
} 

public String getAddForeignKeyConstraintString(String constraintName, 
     String[] foreignKey, String referencedTable, String[] primaryKey, 
     boolean referencesPrimaryKey) { 
    throw new UnsupportedOperationException(
      "No add foreign key syntax supported by SQLiteDialect"); 
} 

public String getAddPrimaryKeyConstraintString(String constraintName) { 
    throw new UnsupportedOperationException(
      "No add primary key syntax supported by SQLiteDialect"); 
} 

public boolean supportsIfExistsBeforeTableName() { 
    return true; 
} 

public boolean supportsCascadeDelete() { 
    return false; 
} 

}

が私を助けてください!

ありがとうございます。

+0

"SQLite JDBCドライバでは実装されていません"はかなり明確です。あなた自身でサポートを実装しない限り、このドライバを使ってBLOBを読むことはできません。 –

+0

しかし、データベースにBLOBデータを書き込むことに問題はありません!そしてこれはどのようにして行われますか?別のSQLite JDBCドライバの実装やそのようなサポートの実装方法の例はありますか? –

答えて

0

Googleの知恵です。 hereは、SQLite JDBCドライバはBLOBサポートをサポートしていますが、実際にはすべての通常の操作を提供するわけではないことを示しています。たとえば、setBytesを実装しますが、setBinaryStreamを実装しません。通常の回避策は、データへのアクセス方法を変更することです。

スタックトレースを取得していないため、これが問題であるかどうかは不明です。 Hibernateに例外メッセージではなくスタックトレースを与えるようにしてください。そのような部分的なサポートが原因で問題が発生した場合は、HibernateにBlobへのアクセス方法を変更させるか、または残念ながらPreparedStatementを使用してHibernateの背後に戻る必要があります。

+0

ありがとうございました。私は準備されたステートメントをこの方法で使用しようとしました。まず、セッションwhith entity.Manager.unwrawp(Session.class)を取得します。私はdoWork関数をsession.doWork(){execute(Connection con){....}と呼び、実行関数ではcon.prepareStatement( "SELECT * FROM logo")でプリペアドステートメントを作成します。結果セットはBLOBバイトを取得しますが、今は "ResultSet closed"エラーが発生し、SQLStateはまだnullです。 –

0

私には解決策があります。私は自分でSQL処理を行わなければなりませんでした。

Iは、(@Injectはサーブレットで使用することができないので、静的)データベースからデータを読み出し、静的メソッドを有する

public static byte[] loadLogo() { 
    byte[] ar = null; 
    Connection con; 
    Statement stmt; 
    String driver = "org.sqlite.JDBC"; 
    String url = "jdbc:sqlite:X:\\Projekte\\Bauer - Rainstar\\Entwickler\\database\\rainstar_ds.sqlite"; 
    try { 
     Class.forName(driver).newInstance(); 
     con = DriverManager.getConnection(url); 
     con.setAutoCommit(false); 

     stmt = con.createStatement(); 

     ResultSet set = stmt.executeQuery("SELECT * FROM logo"); 
     set.next(); 
     ar = set.getBytes("logo_data"); 

     con.close(); 
    } catch (Exception e) { 
     e.printStackTrace(); 
    } 

    return ar; 
} 

私はのHttpServletを実装:

@WebServlet("/images/*") 
public class ImageServlet extends HttpServlet { 

private static final long serialVersionUID = 1L; 

@Override 
protected void doGet(HttpServletRequest req, HttpServletResponse resp) 
     throws ServletException, IOException { 
    OutputStream os = resp.getOutputStream(); 
    byte[] temp = LogoServiceImpl.loadLogo(); 
    os.write(temp); 
} 

}

ページ上で私の写真をページに表示するには、次のように指定する必要があります。

<img src="images/xx" /> 

そして私はまた、web.xmlファイル私は私のイメージファイルをこのように保存された

<servlet> 
    <servlet-name>Image Servlet</servlet-name> 
    <servlet-class>at.beko.rainstar2.ui.controller.ImageServlet</servlet-class> 
</servlet> 

<servlet-mapping> 
    <servlet-name>Image Servlet</servlet-name> 
    <url-pattern>/images/*</url-pattern> 
</servlet-mapping> 

にこれらの行を追加する必要がありました。

@Override 
public void saveLogo(UploadedFile file) { 
    try { 
     Query query = entityManager 
       .createNativeQuery("INSERT INTO 'logo' VALUES (?,?)"); 
     query.setParameter(1, "2"); 
     query.setParameter(2, getBytesFromFile(file)); 
     query.executeUpdate(); 
    } catch (IOException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } 
} 

private byte[] getBytesFromFile(UploadedFile file) throws IOException { 
    InputStream is = file.getInputstream(); 

    long length = file.getSize(); 
    if (length > Integer.MAX_VALUE) { 
     // File is too large 
    } 

    byte[] bytes = new byte[(int) length]; 

    int offset = 0; 
    int numRead = 0; 
    int realLength = bytes.length; 
    while (offset < realLength 
      && (numRead = is.read(bytes, offset, realLength - offset)) >= 0) { 
     offset += numRead; 
    } 

    if (offset < realLength) { 
     throw new IOException("Could not completely read file " 
       + file.getFileName()); 
    } 

    is.close(); 
    return bytes; 
} 

これは私の事前解決です!だから、ハードコードされた部分は気にしないでください^^

関連する問題