4

I am developing a Java web application using Hibernate and JSF/primefaces. am sometimes getting errors like

1) an object with same identifier is already associated with session.

2) failed to load lazy initialization *,no session exist or session is already closed.

I know this is due to improper coding in my app. this is the way am doing aap:

When a user requests for a page(Let it be a list of Employees). the user will get the employee list page(empployeeList.xhtml) EmployeeListMBean is the managed bean for this page. in the managed bean in the constructor, am calling a method populateEmployees(). populateEmployee() will use the EmployeeDao method getAllEmployee() to getAllemployees.

Employee Class goes here:

@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

}

here is my 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;
    }    
}

Question 1) here, in the methods I am closing the session and then return back the result to managedbeans. so in the employee listing page the table list out name dob dateOfHire. and I have a buutton view more detail. on clicking this button, I want to display all projects of selected employee working on using the same managedbeans but, it is giving me error(2), failed to lazyload, no session or session already closed. if I keep the session opened in the getemployeeMethod of dao, I guess that may lead to a memory leak problem, or someother problem. is it so? also, I have tried lazy and eager loading. please give me a clear idea when/how to use these type of fetching. How can I solve this? can I go for filters or facelisteners for solving this?

Question 2) if am trying to edit a project of an employee, and update using session.saveorupadte(), merge(),flush(), am getting an error like this, "an object with same identifier is already associated with session" How can I solve this?

Question 3) I know that sessionfactory is resource consuming. so only single instance is enough for one app. but what about session? for a SINGLE USER of app, only one session is needed? please tell me good strategy for developing such an app.

Thanking you all :)

4

2 回答 2

0

我认为您的第一个问题的答案是您不会在每次使用时都提交会话。我的意思是在 getAllEmployee 和 getEmployeeByEmployeeId 方法中你不会提交你的事务。您可以添加 session.getTransaction.commit(); 我不确定,但您的第一个问题可能会导致第二个问题,因为事务未提交。对于会话的好策略,你可以看看这个

于 2012-04-08T19:08:10.473 回答
0

正如另一个答案中所说,您应该是commiting您已经开始的交易。读取数据时不需要事务。

问题1:延迟加载。

您需要延迟加载 projects,以便它可以在您的视图中自由使用。为此,修改代码如下,

@OneToMany(fetch=FetchType.LAZY)
private List<Project> projects;

问题2:具有相同标识符的对象已经存在。

调试并找出id您要保存的对象是什么。如果没有您的错误的堆栈跟踪,我在这里无能为力。

问题3:会话和会话工厂。

这是本文中两者之间的区别。

SessionFactory 是单个数据存储的 Hibernates 概念,并且是线程安全的,因此许多线程可以同时访问它并请求会话和单个数据库的已编译映射的不可变缓存。SessionFactory 通常只在启动时构建一次。SessionFactory 应该包装在某种单例中,以便可以在应用程序代码中轻松访问它。

Session 是一个轻量级且非线程安全的对象(不,您不能在线程之间共享它),它表示与数据库的单个工作单元。会话由 SessionFactory 打开,然后在所有工作完成后关闭。Session 是持久化服务的主要接口。会话延迟获取数据库连接(即仅在需要时)。为避免创建太多会话,无论调用 currentSession() 方法多少次,都可以使用如下所示的 ThreadLocal 类来获取当前会话。

session因此,在您的代码中,您应该为每次关闭方法时创建一个局部变量并关闭它。

于 2012-04-27T13:38:17.807 回答