Olá pessoal,
me desculpem comentar um post antigo, mas estou enfrentando um problema de performance usando hibernate.
É muito provável que seja a falta de experiência com o framework.
Recursos da aplicação:
Hibernate, partes com Spring, e JSF e Primefaces, banco postgresql
Gostaria de citar meu problema:
Estou montando uma aplicação onde registro algumas entrevistas internas, então tenho dados do funcionário, entrevistador e das questões da entrevista.
De imediato percebe-se que podemos ter 3 tabelas, entretanto o funcionário e o entrevistador fazem parte da mesma tabela funcionário. Então temos 2 tabelas no banco - Funcionário, Entrevistas.
Só tem um detalhe, teremos ainda as tabelas de Datas Salariais, Cargo, Função e Área todas essas tabelas possuem relações com o funcionário.
Tenho uma página de consulta onde será listada todas as entrevistas, hoje temos 400 entrevistas como carga inicial e é nessa página de consulta que há problema de performance.
Eu uso nessa página um datatable. É exatamente o mesmo que está nas demonstrações do primefaces:
http://www.primefaces.org/showcase/ui/datatableComplex.jsf
Eu também adicionei um <p:ajax event=“rowSelect” />, pois as informações mais detalhadas será mostrada em um dialog. Por isso preciso de todos os dados.
Abaixo segue as classes que montei, sei que temos um recurso chamado LAZY e EAGER para consultas @OneToMany, estou usando EAGER pois terei todas as informações de uma só vez, se eu utilizasse o LAZY provavelmente durante a renderização dos dados ele faria todas as outras consultas do mesmo jeito.
Acessando pela internet levou ~1 minuto e 30 segundos para apresentar as 400 entrevistas, pense no usuário clicando no menu de consulta e a página fica ali carregando, eu mesmo não aguentei o tempo que está levando. Já usando a rede local levou ~10 segundos. Mas esses números (400 conforme mencionado acima) tendem a dobrar a cada 3 ou 4 meses.
Minhas questões:
1- Poderiam sugerir um forma melhor de performance ?
2- Quanto ao uso do LAZY, o básico dele eu sei como funciona, mas eu costumo fechar a conexão logo após a query usando session.getTransaction().commit(); e session.close(); então recebo um lazy initialization exception, mas não entendi direito como usar o Open Session in View.
3- Para essa aplicação, o hibernate realmente pode me ajudar, não é ?
Se ficou alguma dúvida na minha explicação é só comentar, desde já agradeço.
Montei as associações mais ou menos assim (possuem pequenas alterações das originais, pois ainda há outros relacionamento e mais colunas):
// FUNCIONARIO
@Service
@Entity
@Table
@SequenceGenerator(name = "pk_sequence_funcionario", sequenceName = "funcionario_id_seq")
public class Funcionario implements Serializable {
private static final long serialVersionUID = 253282986994912255L;
@Id
@Column
@GeneratedValue(strategy = GenerationType.AUTO, generator = "pk_sequence_funcionario")
private Integer id;
@Column
@OrderBy(clause = "nome")
private String nome;
@Column
private String email;
@OneToOne
@JoinColumn(name = "id_cargo")
private Cargo cargo;
@OneToOne
@JoinColumn(name = "id_area")
private Area area;
@OneToMany(mappedBy = "funcionario", targetEntity = Salario.class, fetch = FetchType.EAGER)
@OrderBy(clause = "dataSalario")
private List<Salario> listaSalarios;
@OneToMany(mappedBy = "funcionario", targetEntity = Entrevista.class, fetch = FetchType.EAGER)
@OrderBy(clause = "dataEntrevista ASC")
private Set<Entrevista> listaEntrevista;
// temos ainda mais 4 colunas aqui, omiti para facilitar a leitura
// getters setters
}
// SALARIO
@Service
@Entity
@Table
@SequenceGenerator(name = "pk_sequence_salario", sequenceName = "salario_id_seq")
public class Salario implements Serializable{
private static final long serialVersionUID = -660215567623424277L;
@Id
@Column
@GeneratedValue(strategy = GenerationType.AUTO, generator = "pk_sequence_salario")
private Integer id;
@Column(name="data_entrada")
private Date dataSalario;
@ManyToOne
@JoinColumn(name="id_funcionario")
private Funcionario funcionario;
// getters setters
}
// AREA
@Service
@Entity
@Table
@SequenceGenerator(name = "pk_sequence_area", sequenceName = "area_id_seq")
public class Area implements Serializable {
private static final long serialVersionUID = -172491528235032442L;
@Id
@GeneratedValue(strategy = GenerationType.AUTO, generator = "pk_sequence_area")
@Column
private Integer id;
@Column
private String nome;
// getters setters
}
// CARGO
@Service
@Entity
@Table
@SequenceGenerator(name = "pk_sequence_area", sequenceName = "area_id_seq")
public class Area implements Serializable {
private static final long serialVersionUID = -172491528235032442L;
@Id
@GeneratedValue(strategy = GenerationType.AUTO, generator = "pk_sequence_area")
@Column
private Integer id;
@Column
private String nome;
// getters setters
}
// ENTREVISTA
@Service
@Entity
@Table
@SequenceGenerator(name = "pk_sequence_entrevista", sequenceName = "entrevista_id_seq")
public class Entrevista implements Serializable {
private static final long serialVersionUID = -4555908627091964524L;
@Id
@Column
@GeneratedValue(strategy = GenerationType.AUTO, generator = "pk_sequence_entrevista")
private Integer id;
@ManyToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "id_funcionario")
private Funcionario funcionario;
@ManyToOne
@JoinColumn(name = "id_entrevistador")
private Funcionario entrevistador;
@Column(name = "data_entrevista")
private Date dataEntrevista;
@Column(name = "tecnologia_plataforma")
private String tecnologiaPlataforma;
@Column(name = "sistema_conhecimento")
private String sistemaConhecidos;
@Column(name = "dados_pessoais")
private String dadosPessoais;
// temos ainda mais 10 colunas aqui, omiti para facilitar a leitura
// getters setters
}