LazyInitializationException - не удалось инициализировать прокси - нет сеанса - PullRequest
0 голосов
/ 05 февраля 2019

У меня проблема с LazyInitializationException, и я не знаю, как это исправить.

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);
    }

До того, как проблема была, когда я звонил .getperson = null, но я исправляю вызов findProjectEmployeesWithinDates, запрашивающий тамполучить человека.Но потом я получил исключение, когда я вызвал 'findProjectEmployeesWithinDates'.Код 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;
}

Итак, используя debbug, я увидел, что:

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

он идет в первой строке здесь в цикле for в findProjectEmployeesWithinDates, но не во второй, издесь происходит исключение.

ошибка, которую я получаю

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

в org.hibernate.proxy.AbstractLazyInitializer.initialize (AbstractLazyInitializer.java:165) ~ [hibernate-core-4.3.6.Final.jar: 4.3.6.Final] в org.hibernate.Hibernate.initialize (Hibernate.java:75) ~ [hibernate-core-4.3.6.Final.jar: 4.3.6.Final] в com.xitee.ccpt.4.1.1.RELEASE.jar: na]

Класс сотрудника проекта:

@Entity

@ Table (name = "employee", schema = "ccpt_data") @NamedQuery (name = "Employee.findAll ", query =" SELECT e FROM Employee e ") открытый класс Employee реализует 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;
}

Может кто-нибудь помочь мне с этой проблемой, пожалуйста?

Ответы [ 2 ]

0 голосов
/ 05 февраля 2019

Я бы порекомендовал один из следующих подходов:

1) В вашем методе репозитория findProjectEmployeesWithinDates вы можете сделать

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

}

, чтобы он инициализировал объекты при открытом сеансе

2) Вы можете получить данные, используя запрос

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

Таким образом, Hibernates автоматически заполнит результат выполнения объектами сотрудника и человека

0 голосов
/ 05 февраля 2019
  • Когда вы вызываете метод projectEmployeeRepository.findProjectEmployeesWithinDates, он возвращает List.На данный момент ваша спящая сессия уже закрыта.
  • Таким образом, при чтении объекта ProjectEmployee вам разрешается получать доступ только к этим переменным, относящимся к конкретному объекту, а не к дочерним объектам, специфичным для объекта, поскольку вы используете отложенную инициализацию для своих дочерних объектов.
  • Таким образом, обходной путь заключается воставьте сеанс гибернации открытым или используйте активную выборку или используйте объект класса-оболочки для передачи значений из класса ProjectEmployee в ProjectEmployeeWrapper в методе projectEmployeeRepository.findProjectEmployeesWithinDates, а затем возвращайте объект List из ProjectEmployeeWrapper
...