我正在使用Hibernate和JSF / primefaces开发Java Web应用程序 . 我有时会得到错误
1)具有相同标识符的对象已经与会话相关联 .
2)无法加载延迟初始化 ***** ,没有会话存在或会话已经关闭 .
我知道这是由于我的应用程序编码不当造成的 . 这是我做的事情:
当用户请求页面时(让它成为员工列表) . 用户将获得员工列表页面(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)这里,在我关闭会话的方法中,然后将结果返回给管理员 . 所以在员工列表页面中,表列出了名称dob dateOfHire . 我有一个buutton视图更详细 . 单击此按钮,我想显示使用相同管理员工作的所选员工的所有项目,但是它给了我错误(2),无法延迟加载,没有会话或会话已经关闭 . 如果我在date的getemployeeMethod中保持会话打开,我想这可能会导致内存泄漏问题或其他问题 . 是这样吗?另外,我尝试过懒惰和急切的装载 . 请给我一个清楚的想法何时/如何使用这些类型的提取 . 我怎么解决这个问题?我可以去过滤器或facelisteners来解决这个问题吗?
问题2)如果我正在尝试编辑员工的项目,并使用session.saveorupadte(),merge(),flush()更新,我得到这样的错误,“具有相同标识符的对象已经与会话关联”我怎么解决这个问题?
问题3)我知道sessionfactory是资源消耗 . 因此,对于一个应用程序,只有一个实例就够 Session 怎么样?对于应用程序的单个用户,只需要一个会话?请告诉我开发这样一个应用程序的好策略 .
感谢大家:)
2 回答
正如在另一个答案中所说,你应该_1162851_你已经开始的交易 . 在读取数据时不需要事务 .
您需要lazy load
projects
,以便可以在视图中自由使用 . 为此,请修改如下代码,调试并找出要保存的对象的
id
. 没有错误的堆栈跟踪,我在这里帮助不大 .以下是这两者之间的区别article .
因此,在代码中,您应该为
session
创建一个局部变量,并在每次关闭方法时将其关闭 .我想你的第一个问题's answer is you don' t会在每次使用中提交你的会话 . 我的意思是在getAllEmployee和getEmployeeByEmployeeId方法中,您不提交事务 . 您可以添加
session.getTransaction.commit();
I 'm not sure but your first problem may cause the second one because transaction doesn' t commit . 对于会话的好策略,您可以查看this .