2012-05-08 4 views
0

Hy!sqlite 데이터베이스에서 BLOB 데이터 읽기 -> jpa (최대 절전 모드)

나는 SQLite 데이터베이스에서 BLOB 데이터를 읽고 싶어하지만 난 항상이 오류 메시지 나 JSF, 봄, JPA (최대 절전 모드)를 사용하고

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) 

코드 한 줄을 읽어 :

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 엔티티를 얻습니다 .Manager.unwrawp (Session.class); doWork 함수를 session.doWork() {execute (Connection con) {....}이라고 부르고 실행 함수에서 con.prepareStatement ("SELECT * FROM logo")를 사용하여 준비된 문을 작성한 다음 결과 집합 블롭 바이트를 얻을 수 있습니다.하지만 지금은 "ResultSet 닫힌"오류 및 SQLState 여전히 null입니다. –

0

확인. 나는 해결책이있다. 나는 SQL 처리를 독자적으로 수행해야했습니다.

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

}

(@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을 구현

는 I 데이터베이스로부터 데이터를 판독하는 고정 방법이

페이지에 내 그림을 표시하려면 다음을 지정하기 만하면됩니다.

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

이것은 내 사전 솔루션입니다! 그러니 하드 코딩 된 부분에 신경 쓸 필요가 없습니다 ^^

관련 문제