休眠,会话,延迟加载 [英] Hibernate, session, lazyloading

查看:105
本文介绍了休眠,会话,延迟加载的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在开发一个使用Hibernate和JSF / primefaces的Java Web应用程序。
有时会出现像



这样的错误1)具有相同标识符的对象已与会话关联。



< 2)未能加载延迟初始化 * ,没有会话存在或会话已关闭。



我知道这是由于编码不正确在我的应用程序。
这就是我做aap的方式:



当用户请求一个页面时(让它成为一个Employees列表)。
用户将获得员工列表页面(empployeeList.xhtml)
EmployeeListMBean是此页面的托管bean。
在构造函数的托管bean中调用方法populateEmployees()。
populateEmployee()将使用EmployeeDao方法getAllEmployee()来获取雇员。



Employee Class在这里:

  @Entity 
@Table(name =Employee)
@NamedQueries({
@NamedQuery(name =Employee.getAllEmployee,query =from Employee),
@NamedQuery(name =Employee.findEmployeeByFirstName,query =from Employee where firstName =:firstName),
@NamedQuery名称=Employee.findEmployeeByLastName,查询=从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实现Serializable {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name =EID)
私人长ID;
@Column(name =FIRST_NAME)
private String firstName;
@Column(name =LAST_NAME)
private String lastName;
@Column(name =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)
私人办公室;
@OneToOne(cascade = CascadeType.ALL)
私人住宅地址住宅;
@OneToMany
私人列表< Project>项目;

// getters and setters

}

这里是我的EmployeeDao:

  public class EmployeeDao实现Serializable {
private SessionFactory factory;
私有会话会话;
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();
列表<员工> cities = session.getNamedQuery(Employee.getAllEmployee)。list();
session.close();
返回城市;

$ b $ public Employee getEmployeeByEmployeeId(long employeeId){
factory = HibernateUtil.getSessionFactory();
session = factory.openSession();
session.beginTransaction();
Employee employee =(Employee)session.get(Employee.class,employeeId);
session.close();
返回员工;






$ b问题1)
在这里,在方法我正在关闭会话,然后将结果返回给managedbeans。
,所以在员工列表页面中,列表名称为dob dateOfHire。我有一个buutton查看更多细节。在点击这个按钮时,我想显示选定的员工使用相同的managedbeans的所有项目,但它给我错误(2),lazyload失败,没有会话或会话已经关闭。
如果我保持在dao的getemployeeMethod中打开会话,我想这可能会导致内存泄漏问题或其他问题。是这样吗?
也,我尝试了懒惰和急切的加载。请告诉我何时/如何使用这些类型的抓取。
我该如何解决这个问题?

问题2)
如果试图编辑员工的项目,并使用session.saveorupadte进行更新,可以使用过滤器或facelisteners来解决这个问题吗? (),merge(),flush(),得到这样的错误,一个具有相同标识符的对象已经与会话相关联
我该如何解决这个问题?



问题3)
我知道sessionfactory是耗费资源的。所以只有一个实例就足够用于一个应用程序。但会话呢?
为应用程序的单用户,只需要一个会话?
请告诉我开发这样一款应用的好策略。

感谢大家:)

解决方案

正如在另一个答案中所说的,你应该是提交你已经开始的交易。您在阅读数据时不需要交易。


问题1:延迟加载。


blockquote>

您需要延迟加载 项目,这样它可以在你的视图中自由使用。要做到这一点,请修改下面的代码,

  @OneToMany(fetch = FetchType.LAZY)
private List<项目>项目;




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

调试并找出要保存的对象的 id


问题3:session和sessionfactory。


以下是两者之间的区别:文章


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

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


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


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.

Question 1 : Lazy Loading.

You need to lazy load projects, so that it can be used freely in your view. To do that, modify the code as below,

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

Question 2 : an object with same identifier is already exist.

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.

Question 3 : session and sessionfactory.

Here is the difference between the two from this article.

SessionFactory is Hibernates concept of a single datastore and is threadsafe so that many threads can access it concurrently and request for sessions and immutable cache of compiled mappings for a single database. A SessionFactory is usually only built once at startup. SessionFactory should be wrapped in some kind of singleton so that it can be easily accessed in an application code.

Session is a light weight and a non-threadsafe object (No, you cannot share it between threads) that represents a single unit-of-work with the database. Sessions are opened by a SessionFactory and then are closed when all work is complete. Session is the primary interface for the persistence service. A session obtains a database connection lazily (i.e. only when required). To avoid creating too many sessions ThreadLocal class can be used as shown below to get the current session no matter how many times you make call to the currentSession() method.

So, in your code you should create a local variable for session and close it every time you close the method.

这篇关于休眠,会话,延迟加载的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆