2
respostas

Native Query

Tenho as seguintes classes:

@Entity
@Table(name = "cargos")
public class Cargo {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;
    private String descricao;
    @OneToMany(mappedBy = "cargo", fetch=FetchType.EAGER)
    private List<Funcionario> funcionario;

    {...}
}
@Entity
@Table(name = "funcionarios")
public class Funcionario {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;
    private String nome;
    private String cpf;
    private Double salario;
    private LocalDate dataContratacao;
    @ManyToOne
    @JoinColumn(name = "cargo_id", nullable = false)
    private Cargo cargo;
    @Fetch(FetchMode.SELECT)
    @ManyToMany(fetch = FetchType.EAGER)
    @JoinTable(name = "funcionarios_unidades", joinColumns = {
            @JoinColumn(name = "fk_funcionario") },
            inverseJoinColumns = { @JoinColumn(name = "fk_unidade")})
    private List<UnidadeTrabalho> unidades;

{...}
}
@Entity
@Table(name = "unidades")
public class UnidadeTrabalho {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;
    private String descricao;
    private String endereco;
    @ManyToMany(mappedBy = "unidades", fetch = FetchType.EAGER)
    private List<Funcionario> funcionarios;
    {...}
}

e no meu FuncionarioRepository tenho os métodos:

//JPQL

    @Query("SELECT f FROM Funcionario f WHERE f.nome = :nome AND f.salario >= :salario AND f.dataContratacao = :data")
    List<Funcionario> findNomeSalarioMaiorDataContratacao(String nome, Double salario, LocalDate data);

//Native Query

    @Query(value = "SELECT * FROM funcionarios f WHERE f.data_contratacao >= :data",
    nativeQuery = true)
    List<Funcionario> findDataContratacaoMaior(LocalDate data);

o JPQL funciona mas o Native Query está retornando o seguinte erro:

"Caused by: org.hibernate.LazyInitializationException: could not initialize proxy [br.com.jpa.spring.data.orm.Cargo#1] - no Session"

2 respostas

Tentei inserir @ManyToMany(fetch = FetchType.EAGER) na private List unidades, mas não funcionou.

Olá, Lucas! Parece que você está enfrentando um problema comum ao usar Hibernate e Spring Data JPA, que é a exceção LazyInitializationException.

Este erro geralmente ocorre quando você tenta acessar um objeto que foi carregado de maneira "preguiçosa" (Lazy) fora da sessão do Hibernate em que foi originalmente carregado. No seu caso, parece que o problema está relacionado com o carregamento do objeto Cargo associado ao Funcionario.

Para resolver esse problema, você pode tentar algumas abordagens:

  1. Mudar a estratégia de carregamento para EAGER: Você pode tentar alterar a estratégia de carregamento de LAZY para EAGER na sua entidade Funcionario. Isso fará com que o Hibernate carregue o objeto Cargo no mesmo momento em que o Funcionario for carregado. No entanto, essa abordagem pode ter um impacto no desempenho da sua aplicação, pois o Hibernate carregará todos os objetos Cargo mesmo que eles não sejam necessários.
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "cargo_id", nullable = false)
private Cargo cargo;
  1. Usar a anotação @EntityGraph para carregar o Cargo quando necessário: A anotação @EntityGraph permite especificar quais associações devem ser carregadas em uma determinada consulta. Você pode usar essa anotação na sua consulta para carregar o Cargo juntamente com o Funcionario.
@EntityGraph(attributePaths = {"cargo"})
@Query(value = "SELECT * FROM funcionarios f WHERE f.data_contratacao >= :data",
nativeQuery = true)
List<Funcionario> findDataContratacaoMaior(LocalDate data);
  1. Usar a anotação @Transactional para manter a sessão aberta: A anotação @Transactional pode ser usada para manter a sessão do Hibernate aberta durante toda a execução do método, permitindo que você carregue objetos preguiçosos mesmo fora do método original de carregamento. No entanto, essa abordagem deve ser usada com cuidado, pois manter a sessão aberta por muito tempo pode ter implicações de desempenho.
@Transactional
public List<Funcionario> findDataContratacaoMaior(LocalDate data) {
    // seu código aqui
}

Lembre-se de que cada uma dessas soluções tem suas próprias vantagens e desvantagens, e a escolha da melhor solução depende das necessidades específicas da sua aplicação. Espero ter ajudado e bons estudos!