[RESOLVIDO] Select column from table com Hibernate, Criteria, HQL

Boa tarde!
Tenho uma aplicação que utiliza o Hibernate e estou precisando melhorar a performance.

Observei que todas as minhas queries estão carregando todos os dados da tabela (Classe mapeada no hibernate),
mas em 99% das vezes só preciso do código e descrição desta Classe.

Gostaria de saber se alguém pode me ajudar a melhorar estas queries para eu ganhar performance no meu sistema

segue abaixo Classe mapeada e DAO

Classe TrFiscal

@Entity
@Table(name = “TR_FISCAL”, catalog = “”, schema = “TRANSPORTE”)
@Data @AllArgsConstructor @NoArgsConstructor
@NamedQueries({@NamedQuery(name = “TrFiscal.findAll”, query = “SELECT f FROM TrFiscal f”)})
public class TrFiscal implements Serializable {

private static final long serialVersionUID = 1L;

@Id
@SequenceGenerator(name = "SEQTR_FISCALFISC_CODIGO", sequenceName = "SE_TR_FISCAL", allocationSize=1) 
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SEQTR_FISCALFISC_CODIGO")
@Basic(optional = false)
@Column(name = "FISC_CODIGO", nullable = false)
private Long fiscCodigo;

@Basic(optional = false)
@Column(name = "FISC_MATRICULA", unique = true, nullable = false)
private Long fiscMatricula;

@JoinColumn(name = “PESS_CODIGO”, referencedColumnName = “PESS_CODIGO”, nullable = false)
@ManyToOne(optional = false, cascade=CascadeType.ALL)
private TrPessoa pessCodigo;

}

Classe TrPessoa

@Entity
@Table(name = “TR_PESSOA”, catalog = “”, schema = “TRANSPORTE”)
@Data @AllArgsConstructor @NoArgsConstructor
public class TrPessoa implements Serializable {

private static final long serialVersionUID = 1L;

@Id
@SequenceGenerator(name = "SEQTR_PESSOAPESS_CODIGO", sequenceName = "SE_TR_PESSOA", allocationSize=1) 
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SEQTR_PESSOAPESS_CODIGO")
@Basic(optional = false)
@Column(name = "PESS_CODIGO", nullable = false)
private Long pessCodigo;
	
@Basic(optional = false)
@Column(name = "PESS_NOME", nullable = false, length = 100)
private String pessNome;

@Column(name = "PESS_CPF")
private String pessCpf;

// outros campos mapeados
}

Classe TrFiscalDAOImpl

public class TrFiscalDaoImpl extends GenericDao<TrFiscal, Long> implements TrFiscalDao<TrFiscal, Long> {

// outros metodos

@Override
public List listAll() {
DetachedCriteria criterio = DetachedCriteria.forClass(TrFiscal.class, “entidade”);
criterio.createAlias(“entidade.pessCodigo”, “pess”);
criterio.addOrder(Order.asc(“pess.pessNome”));
return findByCriteria(criterio);
}

public static void main(String[] args) throws DaoException {
TrFiscalDaoImpl vDAO = new TrFiscalDaoImpl();
for (Object o : vDAO.listAll()) {
System.out.println(o);
}
}

}

// query gerada pelo BD
SELECT this_.FISC_CODIGO AS FISC1_9_1_,
this_.FISC_MATRICULA AS FISC2_9_1_,
this_.PESS_CODIGO AS PESS3_9_1_,
pess1_.PESS_CODIGO AS PESS1_29_0_,
pess1_.CADA_CODIGO AS CADA2_29_0_,
pess1_.PESS_CNPJ AS PESS3_29_0_,
pess1_.PESS_CPF AS PESS4_29_0_,
pess1_.PESS_FONE AS PESS5_29_0_,
pess1_.PESS_FOTO AS PESS6_29_0_,
pess1_.PESS_LOGIN AS PESS7_29_0_,
pess1_.PESS_NOME AS PESS8_29_0_
FROM TRANSPORTE.TR_FISCAL this_
INNER JOIN TRANSPORTE.TR_PESSOA pess1_
ON this_.PESS_CODIGO=pess1_.PESS_CODIGO
ORDER BY pess1_.PESS_NOME ASC

Se você quer apenas colunas específicas, pode fazer assim:

SELECT e.colunaA, e.colunaB FROM Entidade e

O resultado dessa query é uma lista de Object[]. Cada posição desse array vai ter a coluna específica. Seguindo o exemplo anterior, a posição 0 vai ter a colunaA e a posição 1 vai ter a colunaB. Sim, tem que fazer cast de Object para o tipo específico, mas como você que fez a query, você sabe o tipo de cada posição.

Com a Critera API, você pode usar os métodos multiselect ou select do CriteriaQuery para especificar as colunas.

http://docs.oracle.com/javaee/7/api/javax/persistence/criteria/CriteriaQuery.html#multiselect-java.util.List-

1 curtida

Boa tarde!

Vendo algumas documentações na internet,
descobri estas 2 formas, usando o HQL desta forma "SELECT e.colunaA, e.colunaB FROM Entidade e"
e usando o Criteria

Mas em ambos os casos vi que teria que preencher meu objeto TrFiscal,
porque em ambos os casos ele me retorna uma lista de Object[]

Eu estava querendo fugir disso,
ou seja, queria uma forma de preencher meu objeto TrFiscal só com os dados da coluna que pesquisei

Se alguém puder me ajudar ficarei muitíssimo grato

É só chamar o construtor do objeto que você quer criar na query. Obviamente, deve existir um construtor naquele objeto que aceita receber os parâmetros que você está passando.

Suponha que você quer fazer uma query que retorna uma lista de Aluno. Aluno não é uma entidade, mas pode ser construida a partir dos atributos de outra entidade (chamada de Entidade aqui). Pode fazer assim:

SELECT NEW br.com.guj.exemplo.Aluno(e.atributo1, e.atributo2) FROM Entidade e

No código, seria algo assim:

final String jpql = "essa query ali de cima";
List<Aluno> alunos = entityManager.createQuery(jpql, Aluno.class).getResultList();

O nome da classe deve aparecer completo, com o pacote, o chamado “fully qualified name”. Nesse caso, a classe Aluno está no pacote br.com.guj.exemplo.

Também dá pra fazer com Criteria API, ficaria algo assim:

CriteriaBuilder cb = // pega cb do Entity Manager
CriteriaQuery<Aluno> cQuery = cb.createQuery(Aluno.class);
Root<Entidade> entidadeRoot = cQuery.from(Entidade.class);
Path<String> pathAtributo1 = entidadeRoot.<String>get("atributo1");
Path<String> pathAtributo2 = entidadeRoot.<String>get("atributo2");
TypedQuery<Aluno> query = entityManager.createQuery(cQuery.select(cb.construct(Aluno.class, pathAtributo1, pathAtributo2)));

boa noite galera!
enfim encontrei a solução pra fazer o SELECT COLUMN FROM TABLE usando o HQL e Hibernate 3

primeiro vc precisa criar um construtor na sua Entity com todas as colunas que deseja retornar na consulta

public TrFiscal(Long fiscCodigo, Long fiscMatricula, Long pessCodigo, String pessNome){
this.fiscCodigo = fiscCodigo;
this.fiscMatricula = fiscMatricula;
this.setPessCodigo(new TrPessoa(pessCodigo, pessNome));
}

depois no DAO você cria o HQL com o NEW

public List listCombobox() throws DaoException{
String hql = “SELECT NEW TrFiscal(f.fiscCodigo, f.fiscMatricula, f.pessCodigo.pessCodigo, f.pessCodigo.pessNome) FROM TrFiscal f JOIN f.pessCodigo AS p”;
return findByHql(hql);
}

ou

public List listCombobox() throws DaoException{
Query query = session.createQuery(“SELECT NEW TrFiscal(f.fiscCodigo, f.fiscMatricula, f.pessCodigo.pessCodigo, f.pessCodigo.pessNome) FROM TrFiscal f JOIN f.pessCodigo AS p”);
return query.list();
}

testei e funcionou com os dois codigos acima

session é um atributo do tipo org.hibernate.Session
query é um atributo do tipo org.hibernateQuery
findByHql é um método de uma superclasse DAO que tem no meu projeto mas que acaba executando query.list()