HibernateとJSF/primefacesを使用してJavaWebアプリケーションを開発しています。次のようなエラーが発生することがあります
1)同じ識別子を持つオブジェクトはすでにセッションに関連付けられています。
2)遅延初期化のロードに失敗しました*、セッションが存在しないか、セッションがすでに閉じられています。
これは私のアプリの不適切なコーディングが原因であることを私は知っています。これはaapを行う方法です:
ユーザーがページを要求したとき(それを従業員のリストとします)。ユーザーは従業員リストページ(empployeeList.xhtml)を取得します。EmployeeListMBeanはこのページの管理対象Beanです。コンストラクターのマネージドBeanで、メソッドpopulateEmployees()を呼び出しています。PopulateEmployee()は、EmployeeDaoメソッドgetAllEmployee()を使用してgetAllemployeesを取得します。
従業員クラスはここに行きます:
@Entity
@Table(name = "Employee")
@NamedQueries({
@NamedQuery(name = "Employee.getAllEmployee", query = "from Employee"),
@NamedQuery(name = "Employee.findEmployeeByFirstName", query = "from Employee where firstName = :firstName"),
@NamedQuery(name = "Employee.findEmployeeByLastName", query = "from Employee where lastName = :lastName"),
@NamedQuery(name = "Employee.findEmployeeByMiddleName", query = "from Employee where middleName = :middleName"),
@NamedQuery(name = "Employee.findEmployeeByOffice", query = "from Employee where office.id = :officeId")
})
public class Employee implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "EID")
private long id;
@Column(name = "FIRST_NAME")
private String firstName;
@Column(name = "LAST_NAME")
private String lastName;
@Column(name = "GENDER")
private String gender;
@Column(name = "DOB")
@Temporal(javax.persistence.TemporalType.DATE)
private Date dateOfBirth;
@Column(name = "DOH")
@Temporal(javax.persistence.TemporalType.DATE)
private Date dateOfHire;
@ManyToOne(cascade= CascadeType.ALL)
private Office office;
@OneToOne(cascade = CascadeType.ALL)
private ResidenceAddress residence;
@OneToMany
private List<Project> projects;
//getters and setters
}
これが私のEmployeeDaoです:
public class EmployeeDao implements Serializable{
private SessionFactory factory;
private Session session;
public void addEmployee(Employee employee){
factory = HibernateUtil.getSessionFactory();
session = factory.openSession();
session.beginTransaction();
session.save(employee);
session.getTransaction.commit();
}
public List<Employee> getAllEmployee(){
factory = HibernateUtil.getSessionFactory();
session = factory.openSession();
session.beginTransaction();
List<Employee> cities = session.getNamedQuery("Employee.getAllEmployee").list();
session.close();
return cities;
}
public Employee getEmployeeByEmployeeId(long employeeId){
factory = HibernateUtil.getSessionFactory();
session = factory.openSession();
session.beginTransaction();
Employee employee = (Employee) session.get(Employee.class, employeeId);
session.close();
return employee;
}
}
質問1)ここで、メソッドでセッションを閉じてから、結果をマネージドBeanに返します。したがって、従業員リストページでは、テーブルに名前dobdateOfHireがリストされます。そして、私はバウトンビューをより詳細に持っています。このボタンをクリックすると、同じ管理対象Beanを使用して作業している選択した従業員のすべてのプロジェクトを表示したいのですが、エラー(2)が発生し、レイジーロードに失敗し、セッションがないか、セッションがすでに閉じられていません。daoのgetemployeeMethodでセッションを開いたままにしておくと、メモリリークの問題やその他の問題が発生する可能性があると思います。そうですか?また、遅延読み込みと熱心な読み込みを試しました。これらのタイプのフェッチをいつ/どのように使用するかを明確に教えてください。どうすればこれを解決できますか?これを解決するためにフィルターやフェイスリスナーを探すことはできますか?
質問2)従業員のプロジェクトを編集し、session.saveorupadte()、merge()、flush()を使用して更新しようとすると、「同じ識別子を持つオブジェクトはすでにセッションに関連付けられています」というエラーが発生します。どうすればこれを解決できますか?
質問3)sessionfactoryはリソースを消費していることを知っています。したがって、1つのアプリには1つのインスタンスだけで十分です。しかし、セッションはどうですか?アプリのシングルユーザーの場合、必要なセッションは1つだけですか?そのようなアプリを開発するための良い戦略を教えてください。
みなさん、ありがとうございました:)