Hibernate / JSF アプリケーションで MySQL データベースから BLOB を取得する
質問
JSF 2.0 アプリケーションで Java を使用してデータベースから BLOB データを適切に取得する際に問題が発生しています。私が抱えている最初の問題は、「file」という名前の Blob のゲッター メソッドで、「基本属性は次の型のみにすることができます...」というエラーが表示され、基本的に Blob オブジェクトを返すことができないことを示しています。私のコードは以下のようになります。エラーがあってもコードはコンパイルされます。テストメソッド (以下のコードの最後の部分) を作成し、テストしようとしましたが、実行時エラーが発生します。
コントローラBean
import java.sql.Blob;
@Entity
@Table(named = "files")
@NamedQueries( {
@NamedQuery(name = "MyBlob.getBlob",
query = from MyBlob WHERE fileId =: fileId")
})
public class MyBlob implements Serializable {
private Integer fileId;
private Blob file;
...
public Integer getFileId() {
return fileId;
}
public void setFileId() {
this.fileId = fileId;
}
public Blob getFile() {
return file;
}
public void setFile(Blob file) {
this.file = file;
}
....
}
BlobDao.java BLOB を取得するファイル メソッド
public MyBlob getBlob(Integer fileId) throws HibernateException {
Session session = getSessionFactory().openSession();
try {
MyBlob blob = (MyBlob)session.getNamedQuery("MyBlob.getBlob").setInteger("fileId", fileId).uniqueResult();
return blob;
} catch(HibernateException e) {
throw new HibernateException(e);
} finally {
session.close();
}
}
テストダオ.java
@Test
public void testBlob() {
MyBlob test = blobdao.getBlob(1); // 1 is a fileId that exists in the DB with a blob image file.
Blob blob = test.getFile();
try {
System.out.println(blob.length)); //this prints a number but I dont think the right one.
if(blob.length > 0 ) {
System.out.println(blob.toString() ); //errors out here
}
} catch(SQLException e) {
return System.out.println("Failed");
}
}
自分がこれを正しくやっているのか全く自信がありません。助けていただければ幸いです。ありがとう。
解決
「file」という名前の Blob の getter メソッドで、「基本属性は次の型のみにすることができます...」というエラーが表示され、基本的に Blob オブジェクトを返すことができないことを示しています。
確かに、 java.sql.Blob
Hibernate/JPA でマップできる永続フィールドまたはプロパティではありません。JPAの仕様は次のようになります。
2.1.1 永続フィールドとプロパティ
...
エンティティの永続的なフィールドまたはプロパティは、次のタイプである場合があります。Java のプリミティブ型。
java.lang.String
;他のJavaシリアル化可能なタイプ(プリミティブタイプのラッパーを含む、java.math.BigInteger
,java.math.BigDecimal
,java.util.Date
,java.util.Calendar
,java.sql.Date
,java.sql.Time
,java.sql.Timestamp
、ユーザー定義のシリアル化可能なタイプ、byte[]
,Byte[]
,char[]
, 、 そしてCharacter[]
);列挙型;エンティティタイプおよび/またはエンティティタイプのコレクション。埋め込み可能なクラス(セクション2.1.5を参照)。
おそらく使用する必要があります Lob
注釈を付けて属性タイプを変更します。仕様から:
9.1.19 Lob アノテーション
LOBアノテーションは、データベースがサポートする大きなオブジェクトタイプの大きなオブジェクトとして永続的なプロパティまたはフィールドを持続する必要があることを指定します。ポータブルアプリケーションは、データベースLOBタイプにマッピングするときにLOBアノテーションを使用する必要があります。の
Lob
注釈は、と組み合わせて使用できますBasic
注釈。あLob
バイナリまたは文字タイプのいずれかです。のLob
タイプは、永続的なフィールドまたはプロパティのタイプから推測され、文字列と文字ベースのタイプを除き、デフォルトはBLOBになります。...
例 1:
@Lob @Basic(fetch=EAGER) @Column(name="REPORT") protected String report;
例 2:
@Lob @Basic(fetch=LAZY) @Column(name="EMP_PIC", columnDefinition="BLOB NOT NULL") protected byte[] pic;
参考文献
- JPA 1.0仕様
- 2.1.1項「永続フィールドとプロパティ」
- 9.1.19項「Lobアノテーション」
私の正確な要件は、Blob または byte[] としてデータベースから Blob を取得し、機能するものは何でも、それを何らかの方法で有効な InputStream オブジェクトに変換することです。
どうですか ByteArrayInputStream(byte[])
?
他のヒント
私はBlob
オブジェクトがあなたのエンティティである推測しています。
それはあなたがそれにも印刷する場合に役立つかもしれない。
を確認してくださいBlob
戻りbyte[]
@Basic(fetch = FetchType.LAZY)
@Lob
@Column(length = 104857600, nullable = false)
private byte[] data;