2017-03-06 9 views
3

私はHibernate 5.2.5を使用します(kotlinとspring 4.3.5も使用します)。クラスのフィールドの一部を遅延ロードします。しかし、問題は、すべてのフィールドが即座にロードされることです。私はHibernate.initialize()も使用しない特別なHibernate設定はありません。Hibernateは 'lazy'フェッチタイプを無視してすぐにプロパティをロードします

@Entity(name = "task") 
@Table(name = "tasks") 
@NamedQueries(
     NamedQuery(name = "task.findById", query = "SELECT t FROM task AS t WHERE t.id = :id") 
) 
class Task { 

    @Id 
    @GeneratedValue(strategy = GenerationType.IDENTITY) 
    var id: Int? = null 

    @ManyToOne(fetch = FetchType.LAZY) 
    @JoinColumn(name = "author_id", nullable = false) 
    lateinit var author: User 

    @OneToOne(fetch = FetchType.LAZY, mappedBy = "task") 
    var edit: TaskEdit? = null 
} 

これは私がどのように照会

TaskRepoImplです:

override fun findById(id: Int): Task? { 
    val task = getCurrentSession().createNamedQuery("task.findById", Task::class.java) 
      .setParameter("id", id) 
      .uniqueResult() 
    return task 
} 

TaskService:

@Transactional 
fun find(id: Int): Task? { 
    return taskRepo.findById(id) 
} 

そして出力:

Hibernate: select task0_.id as id1_1_, task0_.author_id as author_i3_1_ from tasks task0_ where task0_.id=? 
Hibernate: select user0_.id as id1_3_0_, user0_.enabled as enabled2_3_0_, user0_.name as name3_3_0_, user0_.password as password4_3_0_ from users user0_ where user0_.id=? 
Hibernate: select taskedit0_.id as id1_0_0_, taskedit0_.task_id as task_id3_0_0_, taskedit0_.text as text2_0_0_ from task_edits taskedit0_ where taskedit0_.task_id=? 

私のコードに何が違うのか、Hibernateにプロパティを遅延ロードさせる方法を教えてください。ありがとうございました!

+0

を[この回答](http://stackoverflow.com/a/36143746/4754790は)ときの選択肢の概要を説明します子エンティティによってマッピングされたテーブルに外部キーがある、怠惰な1対1の関連付けになります。 –

答えて

1

Hibernateは自分のオブジェクトをプロキシすることはできません。 この問題には、少なくとも3つのよく知られた解決策があります。 最も簡単なのは、1対多の関係を偽造することです。これは、コレクションの遅延読み込みが単一ヌル可能プロパティの読み込みが遅いためには簡単ですが、複雑なJPQL/HQLクエリを使用すると、このソリューションは一般的に非常に不便です。 もう1つは、ビルド時バイトコード計測を使用することです。詳細は、Hibernateのドキュメントを参照してください:19.1.7。遅延プロパティのフェッチを使用します。この場合、@ LazyToOne(LazyToOneOption.NO_PROXY)アノテーションを1対1の関係に追加して、それを怠惰にする必要があることに注意してください。フェッチをLAZYに設定するだけでは不十分です。 最後の解決策は、ランタイムバイトコード計測を使用することですが、本格的なJEE環境でJPAプロバイダとしてHibernateを使用している人にのみ機能します(この場合、 "hibernate.ejb.use_class_enhancer"をtrueに設定すると、設定)、またはランタイムウィービングを行うようにSpringを設定したHibernateを使用することができます(古いアプリケーションサーバによってはこれを達成できない場合があります)。この場合、@ LazyToOne(LazyToOneOption.NO_PROXY)注釈も必要です。

@Entity 
public class Animal implements FieldHandled { 
private Person owner; 
private FieldHandler fieldHandler; 

@OneToOne(fetch = FetchType.LAZY, optional = true, mappedBy = "animal") 
@LazyToOne(LazyToOneOption.NO_PROXY) 
public Person getOwner() { 
    if (fieldHandler != null) { 
    return (Person) fieldHandler.readObject(this, "owner", owner); 
    } 
    return owner; 
} 

public void setOwner(Person owner) { 
    if (fieldHandler != null) { 
    this.owner = fieldHandler.writeObject(this, "owner", this.owner, owner); 
    return; 
    } 
    this.owner = owner; 
} 

public FieldHandler getFieldHandler() { 
    return fieldHandler; 
} 

public void setFieldHandler(FieldHandler fieldHandler) { 
    this.fieldHandler = fieldHandler; 
} 
} 

あなたはこの試みることができます: http://justonjava.blogspot.in/2010/09/lazy-one-to-one-and-one-to-many.html

参照: Why Lazy loading not working in one to one association?

+0

最初の問題は、メソッドがオープンではなかったことです。そのため、Hibernateはプロキシを作成できませんでした。第2の問題は、あなたが言ったように、1対1のマッピングでした。それがなぜそうであるかの良い記述はここにあります:http://stackoverflow.com/questions/1444227/making-a-onetoone-relation-lazy – awfun

+0

あなたの答えのソースの重要な部分を引用してください。 –

関連する問題