2

多数の外部キー関係を持つデータベースの ORM として Hibernate を使用しています。問題は、これらの関連するデータセットをフェッチしたい場合とそうでない場合があるため、これらのコレクションで「フェッチ」を「遅延」に設定したことです。残念ながら、セッションが閉じられているため、これらのオブジェクトをシリアライズしようとするたびに、Hibernate は LazyInitializationException をスローします。OpenSessionInView フィルターを使用すると、Hibernate がこれらのコレクションにデータを入力するだけになり、そもそも遅延コレクションを持つという目的全体が無効になります。

LIE をトリガーせずに、すべての遅延コレクションにデータを入力する必要なく、POJO に入力されたデータをシリアル化または抽出する簡単な方法はありますか?

編集:これは、Departments と 1 対多の関係にある子である "Departments" と "Employees" の 2 つのテーブルを処理して、作業しようとしているコードの例です。データベースにリストされている部門を表示できるようにしたいのですが、その部門に属するすべての従業員をロードする必要はありません。

部門:

package com.test.model;
// Generated Apr 7, 2012 7:10:28 PM by Hibernate Tools 3.4.0.CR1

import java.util.HashSet;
import java.util.Set;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import static javax.persistence.GenerationType.IDENTITY;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;

/**
 * Departments generated by hbm2java
 */
@Entity
@Table(name="Departments"
    ,catalog="test"
)
public class Departments  implements java.io.Serializable {


     private Integer id;
     private String name;
     private Set<Employees> employeeses = new HashSet(0);

    public Departments() {
    }


    public Departments(String name) {
        this.name = name;
    }
    public Departments(String name, Set employeeses) {
       this.name = name;
       this.employeeses = employeeses;
    }

     @Id @GeneratedValue(strategy=IDENTITY)


    @Column(name="Id", unique=true, nullable=false)
    public Integer getId() {
        return this.id;
    }

    public void setId(Integer id) {
        this.id = id;
    }


    @Column(name="Name", nullable=false)
    public String getName() {
        return this.name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @OneToMany(fetch=FetchType.LAZY, mappedBy="departments")
    public Set<Employees> getEmployeeses() {
        return this.employeeses;
    }

    public void setEmployeeses(Set employeeses) {
        this.employeeses = employeeses;
    }
}

従業員:

package com.test.model;
// Generated Apr 7, 2012 7:10:28 PM by Hibernate Tools 3.4.0.CR1


import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import static javax.persistence.GenerationType.IDENTITY;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;

/**
 * Employees generated by hbm2java
 */
@Entity
@Table(name="Employees"
    ,catalog="test"
)
public class Employees  implements java.io.Serializable {


     private Integer id;
     private Departments departments;
     private String firstName;
     private String lastName;

    public Employees() {
    }

    public Employees(Departments departments, String firstName, String lastName) {
       this.departments = departments;
       this.firstName = firstName;
       this.lastName = lastName;
    }

     @Id @GeneratedValue(strategy=IDENTITY)


    @Column(name="Id", unique=true, nullable=false)
    public Integer getId() {
        return this.id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    @ManyToOne(fetch=FetchType.LAZY)
    @JoinColumn(name="DepartmentsId", nullable=false)
    public Departments getDepartments() {
        return this.departments;
    }

    public void setDepartments(Departments departments) {
        this.departments = departments;
    }


    @Column(name="FirstName", nullable=false)
    public String getFirstName() {
        return this.firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }


    @Column(name="LastName", nullable=false)
    public String getLastName() {
        return this.lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }
}

私のアクション クラス (Struts2 XSLT の結果によってシリアル化されます):

package com.test.view;

import java.util.List;

import java.util.Iterator;

import com.opensymphony.xwork2.ActionSupport;
import com.test.controller.DepartmentsManager;
import com.test.model.Departments;
import com.test.util.HibernateUtil;

public class DepartmentsAction extends ActionSupport {
private DepartmentsManager departmentsManager;
private List<Departments> departmentsList;

public DepartmentsAction() {
    this.departmentsManager = new DepartmentsManager();
}

public String list() {
    this.departmentsList = departmentsManager.list();
    System.out.println("Execute called");
    HibernateUtil.createDTO(departmentsList);
    return SUCCESS;
}

public List<Departments> getDepartmentsList() {
    return departmentsList;
}

public void setDepartmentsList(List<Departments> departmentsList) {
    this.departmentsList = departmentsList;
}
}

My Manager クラス (部門のリストを作成するために Action クラスが呼び出すクラス):

package com.test.controller;

import java.util.List;

import java.util.Iterator;

import org.hibernate.Criteria;
import org.hibernate.Hibernate;
import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;

import com.test.model.Departments;
import com.test.util.HibernateUtil;

public class DepartmentsManager {
public List<Departments> list() {
    Session session = HibernateUtil.getSessionFactory().getCurrentSession();
    session.beginTransaction();
    List<Departments> set = null;
    try {
        Query q = session.createQuery("FROM Departments");
        /*Query q = session.createQuery("FROM Departments d JOIN FETCH d.employeeses e");*/
        q.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
        set = (List<Departments>) q.list();
    } catch (HibernateException e) {
        e.printStackTrace();
        session.getTransaction().rollback();
    }
    session.getTransaction().commit();
    return set;
}
}
4

2 に答える 2

2

遅延コレクションは、トランザクションのスコープ内でのみ機能します (所有エンティティが DB から取得された場合)。言い換えると、トランザクション スコープ外の、ロードされていない遅延サブエンティティまたはコレクションを持つ Hibernate エンティティを渡すべきではありません。

別のエンティティを作成するか、エンティティを JSP に渡したい場合は lazy="false" を使用するか、シリアライゼーション コードなどを使用する必要があります。

于 2012-04-16T21:01:53.087 に答える
0

view 内で遅延読み込みを管理する 2 つの簡単な方法:

  • トランザクション ビューを使用する (ビュー呼び出しを JTA トランザクションにラップすることで構成されます (アプリケーション管理など)

  • Bean で拡張永続コンテキストを使用し、それを使い終わったら明示的にフラッシュします。これは、遅延オブジェクトをロードできるようになるとすぐに意味します。

詳細については、この投稿とそれに属する回答を確認してください。

JSF ビューでの JPA 遅延読み込みコレクション - フィルターを使用するよりも良い方法ですか?

于 2012-04-16T23:37:48.933 に答える