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 :)
As told in the other answer, you should be
commiting
the transactions you have started. The Transactions are not needed while you are reading the data.You need to lazy load
projects
, so that it can be used freely in your view. To do that, modify the code as below,Debug and find out what is the
id
of the object you are going to save. I can't much help here without a stacktrace of your error.Here is the difference between the two from this article.
So, in your code you should create a local variable for
session
and close it every time you close the method.I think your first question's answer is you don't commit your session in every usage. I mean in getAllEmployee and getEmployeeByEmployeeId methods you don't commit your transaction. You can add
session.getTransaction.commit();
I'm not sure but your first problem may cause the second one because transaction doesn't commit. For the good strategy with session you can look this.