2009-07-17 14 views
15

このグーグルについては、たくさん見つけられますが、私はこの問題の解決策を見つけられませんでした。休止状態でclobをゆっくり読み込む

基本的に私が持っているのは、要求に応じてロードしたい特定のクラスの大きなCLOBです。これを行うには素朴な方法は、次のようになります。どうやら原因私はOracleドライバを使用しているという事実に、しかし動作しません

class MyType { 

    // ... 

    @Basic(fetch=FetchType.LAZY) 
    @Lob 
    public String getBlob() { 
    return blob; 
    } 
} 

は、すなわち、LOBオブジェクトは、単純なハンドルとして扱われませんが、常にロードされます。それで、私は私の仕事から信じるように導かれました。怠惰なプロパティローディングのための特別な計測を使用するソリューションがありますが、Hibernateのドキュメントでは正しく動作することに興味がないと思われるようですので、私はむしろそのルートにはいきません。特に、余分なコンパイルパスを実行する必要があります。

私が想像した次の解決策は、このオブジェクトを別のタイプに分離して関連付けを定義することでした。残念ながら、ドキュメントは競合する情報を提供しますが、共有プライマリキーとのOneToOneの関連付けでは遅延読み込みが機能しません。私はManyToOneとしてアソシエーションの片側を設定したいと思いますが、プライマリキーが共有されているときにこれを行う方法はわかりません。

だから誰でもこのことについて最善の方法を提案できますか?

+0

Oracleで動作しない理由を明確にしてください。 – skaffman

+0

私はそのビットをもう少し詳しく解説しましたが、私は正確な問題が何であるかについては完全にはわかりません(詳細についてはあいまいです)。マッピングに問題がある場合は、適切にclobを読み込む必要があるものを与えることができますか? – wds

+0

Oracleで試したところ、失敗した場合、どのように失敗しましたか? – skaffman

答えて

5

thisによると、PostgreSQLはBlobを本当に怠惰なものとして実装しています。だから、最良の解決策は、BLOBを別のテーブルに移動することです。共有プライマリキーを使用する必要がありますか?なぜあなたはこのような何かはありません。

public class MyBlobWrapper { 
    @Id 
    public Long getId() { 
     return id; 
    } 
    @Lob 
    public String getBlob() { 
     return blob; 
    } 
    @OneToOne(fetch=FetchType.LAZY,optional=false) 
    public MyClass getParent() { 
     return parent; 
    } 
} 
+0

ブロブは同じテーブルのフィールドなので、はい、共有プライマリキーを使用する必要があります。あなたのアプローチは、所有側にoptional = "false"が設定されている限り動作します。オブジェクトがnullのときにひどく壊れてしまうと思いますか? – wds

+0

D'oh。もちろん、主キーが存在するため、nullになることはありません。それはちょうどnullのクローブフィールドになります。思考のビット、ありがとう。 :-) – wds

+0

これは、親側btw(MyType)で必要なマッピングです。 @OneToOne(fetch = FetchType.LAZY、optional = false) – wds

4

の代わりに休止状態の注釈とともにequilibristicsをやって、一つはちょうどClob(またはBlob)にStringからフィールドを変換してみてください可能性があります

@Lob 
@Basic(fetch=FetchType.LAZY) 
@Column(name = "FIELD_COLUMN") 
public Clob getFieldClob() { 
    return fieldClob; 
} 

public void setFieldClob(Clob fieldClob) { 
    this.fieldClob = fieldClob; 
} 

@Transient 
public String getField() 
{ 
    if (this.getFieldClob()==null){ 
    return null; 
    } 
    try { 
    return MyOwnUtils.readStream(this.getFieldClob().getCharacterStream()); 
    } catch (Exception e) { 
    e.printStackTrace(); 
    } 

    return null; 
} 

public void setField(String field) 
{ 
    this.fieldClob = Hibernate.createClob(field); 
} 

が勤務します私(フィールドは遅れてOracleにロードされ始めました)。

+0

これは、フィールドが遅延してロードされる原因になりますか?私はこれを伝えるだけで、便利なgetter/setterを追加して文字列としてロブにアクセスできますか? –

+0

@BenGeorge Lobアノテーションは、質問のStringゲッターではなく、私の答えでClobゲッターに置かれていることに注意してください。私はClobフィールドを直接使用するのではなく、一時的なゲッターを通してのみ使用します。警告:私がこれを試したHibernateのバージョンは、正しく覚えていれば3.2でした。ロードが実際に怠惰であることを確認するために、私はWiresharkを使用してデータベースとの間のトラフィックを検査しました。 –

3

あなたが休止状態を使用しているように見えるので、あなたの問題は、次の休止状態機能に関連している場合、私は疑問に思う:

Using Lazy Properties Fetching

Hibernate3では個々のプロパティの遅延フェッチをサポートしています。この 最適化手法は、フェッチグループとも呼ばれます。 これは主にマーケティング機能です。行の読み込みを最適化することは、列の読み込みを最適化するよりもはるかに重要です。 しかし、極端な場合には、クラスのいくつかのプロパティをロードするだけで便利な場合があります。 の例では、レガシーテーブルに数百の列があり、データ モデルを改善することはできません。

レイジープロパティロードは、ビルド時バイトコードインストルメンテーションを必要とします。 あなたの永続クラスが拡張されていない場合、Hibernateは怠惰な プロパティ設定を無視し、即時取得に戻ります。

Bytecode Instrumentation for Hibernate Using Mavenを参照してください。

0

オールドポストが、私を助けたのは、@ TadeuszKopecのおかげで答えました。

JPAでBLOBの遅延読み込みを行うのは難しいようです。私は@OneToOneの関連付けを試みましたが、それは助け以上に複雑です。 私はMyClassの(親と同じテーブル、同じid。)との関連で、別のクラスにバイトを移動:

@Entity 
@Table(name="MyTable") 
public class MyBlobWrapper{ 

    @Id 
    @Column(name = "id") // id of MyTable, same as MyClass 
    private Long id; 

    @Lob 
    private byte[] bytes; 
} 

@Entity 
@Table(name="MyTable") 
public class MyClass{ 

    @Id 
    @Column(name = "id") 
    private Long id; 
    // other fields ..... 
} 

ちょうどブロブを保存する前に、親をフラッシュすることを忘れないでください:

em.persist(parent); 
em.flush(); 
em.merge(new MyBlobWrapper(parent_id,new byte[1000])); 

今すぐpdfだけを読み込むことができます:

String query1 = " select PDF from MyBlobWrapper PDF where PDF.id = :id"; 

私はちょうどJPAの初心者です。