简体   繁体   中英

LazyInitializationException - could not initialize proxy - no Session

I have a problem with LazyInitializationException and I don't know how to fix it.

for (Long id : employeeIds)
    {
        List<ProjectEmployee> projectEmployeeList = projectEmployeeService.findProjectEmployeesWithinDates(id,
                startDate, endDate);

        // if no data, then continue with next employee
        if (projectEmployeeList.isEmpty())
        {
            continue;
        }

        gridCreated = true;

        Employee employee = projectEmployeeList.get(0).getEmployee();
        Label titleLabel = new Label(employee.getPerson().getSurname() + " " + employee.getPerson().getName() + " ["
                                     + employee.getRole().getHumanizedRole() + "]");
        titleLabel.setStyleName("header-bold");

        ProjectEmployeePanel projectEmployeePanel = new ProjectEmployeePanel(id, startDate, endDate);
        gridPanelsLayout.addComponents(titleLabel, projectEmployeePanel);
    }

Before the problem was when I was calling .getperson=null but I fix the call findProjectEmployeesWithinDates asking there to get the person. But then I got the exception when I call the 'findProjectEmployeesWithinDates'. The code findProjectEmployeesWithinDates:

    public List<ProjectEmployee> findProjectEmployeesWithinDates(Long employeeId, LocalDate startDate, LocalDate endDate) {
    List<Long> list = new ArrayList<>();
    list.add(employeeId);
    List<ProjectEmployee> listProjectEmployees = projectEmployeeRepository.findProjectEmployeesWithinDates(list,
            LocaleUtils.getDateFromLocalDate(startDate, LocaleUtils.APPLICATION_DEFAULT_ZONE_ID),
            LocaleUtils.getDateFromLocalDate(endDate, LocaleUtils.APPLICATION_DEFAULT_ZONE_ID));
    for (ProjectEmployee pe : listProjectEmployees)
    {
        Hibernate.initialize(pe.getEmployee());
        Hibernate.initialize(pe.getEmployee().getPerson());

    }
    return listProjectEmployees;
}

So using debbug i saw that :

 Hibernate.initialize(pe.getEmployee()); ----line 105
Hibernate.initialize(pe.getEmployee().getPerson()); ---line 106

it goes at the first line here at the for loop in the findProjectEmployeesWithinDates but not at the second, and this is where the exception happens.

the error I get

Caused by: org.hibernate.LazyInitializationException: could not initialize proxy - no Session

at org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:165) ~[hibernate-core-4.3.6.Final.jar:4.3.6.Final] at org.hibernate.Hibernate.initialize(Hibernate.java:75) ~[hibernate-core-4.3.6.Final.jar:4.3.6.Final] at com.xitee.ccpt.service.ProjectEmployeeService.findProjectEmployeesWithinDates(ProjectEmployeeService.java:105) ~[classes/:na] at com.xitee.ccpt.service.ProjectEmployeeService$$FastClassBySpringCGLIB$$63bfc6f9.invoke() ~[spring-core-4.1.1.RELEASE.jar:na]

Project Employee class:

@Entity

@Table(name = "employee", schema = "ccpt_data") @NamedQuery(name = "Employee.findAll", query = "SELECT e FROM Employee e") public class Employee implements Serializable { private static final long serialVersionUID = 1L;

@Id
@Column(name = "employee_id")
@SequenceGenerator(name = "EMPLOYEE_ID_GENERATOR", sequenceName = "employee_id_seq", allocationSize = 1)
@GeneratedValue(strategy = GenerationType.AUTO, generator = "EMPLOYEE_ID_GENERATOR")
private Long employeeId;

@OneToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "person_id")
private Person person;

@Column(name = "monthly_cost")
private String monthlyCost;

@Enumerated(EnumType.STRING)
@Column(name = "role")
private EmployeeRole role;

@Column(name = "employee_manager")
private String employeeManager;

@Column(name = "obsolete")
private Boolean obsolete;

@Column(name = "bank_account_number")
private String bankAccountNumber;

@Column(name = "last_employer")
private String lastEmployer;

@Column(name = "starting_day")
private String startingDay;

@Column(name = "hours")
private Short hours;

@OneToMany(mappedBy = "employee", cascade =
    {
     CascadeType.ALL
    }, orphanRemoval = true)
private Set<EmployeeWorkload> employeeWorkloads;

@OneToMany(mappedBy = "employee", fetch = FetchType.LAZY, orphanRemoval = true)
private Set<ProjectEmployee> projectEmployee;

@OneToMany(mappedBy = "employee", cascade =
    {
     CascadeType.PERSIST
    }, orphanRemoval = true)
private Set<Qualification> qualifications;

@OneToMany(mappedBy = "employee", cascade =
    {
     CascadeType.PERSIST
    }, orphanRemoval = true)
private List<CareerExperience> careerExperiences;

@Transient
private Map<Integer, String> exportOptions;

@OneToMany(mappedBy = "employee", fetch = FetchType.LAZY, orphanRemoval = true)
private Set<ProjectEmployeeRejection> projectEmployeeRejections;

@Transient
private boolean decrypted = true; // allows editing and viewing for users with no encryption rights

/**
 * Initialization vector used for encryption of this employee or NO_KEY if no encryption was used
 *
 * @since 0.4.0
 */
@Column(name = "iv")
private String iv;

@Column(name = "cis_employee_id")
private Long cISEmployeeId;

@Column(name = "experience_summary")
private String experienceSummary;

@Enumerated(EnumType.STRING)
@Column(name = "employee_job_type")
private EmployeeJobType employeeJobType;

@Column(name = "ending_day")
@Type(type = "date")
private Date endingDay;

@Column(name = "main_skill")
private String mainSkill;

public Employee()
{
}

public Long getEmployeeId()
{
    return employeeId;
}

public void setEmployeeId(Long employeeId)
{
    this.employeeId = employeeId;
}

public Person getPerson()
{
    return person;
}

public void setPerson(Person person)
{
    this.person = person;
}

public String getExperienceSummary()
{
    return experienceSummary;
}

public void setExperienceSummary(String experienceSummary)
{
    this.experienceSummary = experienceSummary;
}

Can anyone help me with this problem, please?

I would recommend one of the following approaches:

1) In you repository method findProjectEmployeesWithinDates you can do

for (ProjectEmployee pe : listProjectEmployees)
{
    pe.getEmployee().getPerson();

}

so it will initialize objects while session is open

2) You can fetch data using query

  SELECT * FROM ProjectEmployee pe JOIN FETCH pe.employee e JOIN FETCH e.person

In this way Hibernates will populate execution result with employee and person objects automatically

  • When you call projectEmployeeRepository.findProjectEmployeesWithinDates method it returns List. At this point of time your hibernate session is already closed.
  • So when read the ProjectEmployee object you are allowed to access only those object specific variables and not object specific child objects since you are using lazy initialization for your child objects.
  • So the workaround is to keep your hibernate session open or use eager fetch or use a wrapper class object to transfer values from ProjectEmployee class to ProjectEmployeeWrapper within projectEmployeeRepository.findProjectEmployeesWithinDates method and then return the List of ProjectEmployeeWrapper object

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM