Como fazer o Criteria criar o objeto, selecionando algumas colunas?

16 respostas
xandevieira

Como fazer o Criteria criar o objeto, selecionando algumas colunas?
ex.

Criteria criteria = getCurrentSession().createCriteria(Titulo.class, "t");
			ProjectionList projection = Projections.projectionList();
			projection.add(Projections.property("t.tituloPK.nuTitulo"));
			projection.add(Projections.property("t.cdDocumento"));
			projection.add(Projections.property("t.nuDocumento"));
			projection.add(Projections.property("d.deHistoricoCtb"));
			criteria.setProjection(projection);

			criteria.createAlias("t.documento", "d");
			criteria.createAlias("t.credor", "c");
			criteria.add(Restrictions.eq("t.cdEmpresa", contabil.getContabilPK().getCdEmpresa()));
			criteria.add(Restrictions.between("t.dtContabil", contabil.getDtConsulta(), contabil.getDtFimGeracao()));
			criteria.add(Restrictions.eq("d.flContabilizar", "S"));
			criteria.addOrder(Order.asc("t.dtContabil"));
			

			List<Titulo> list = criteria.list();

No meu exemplo ele esta criando arrais com os campos de ProjectionList.
Gostaria que fosse criado o objeto Titulo com os campos, bem como objeto Documento.

Tem como?
Já tentei a documentação mas não fui feliz.

16 Respostas

R
Criteria criteria = getCurrentSession().createCriteria(Titulo.class, "t");
//Regras da consulta e do resultado
criteria..setResultTransformer(new AliasToBeanResultTransformer(Titulo.class));
xandevieira

No meu exemplo estou selecionando Titulo, com join Documento e Credor.
O transformer não cria a estrutura esperada.
Ou seja, ele cria o Titulo com os campos selecionados, mas não cria o Documento nem o Credor.

fbl.lucas

avsouza:
No meu exemplo estou selecionando Titulo, com join Documento e Credor.
O transformer não cria a estrutura esperada.
Ou seja, ele cria o Titulo com os campos selecionados, mas não cria o Documento nem o Credor.

Então se você quer uma lista de Titulo com Documento e Credor pra que ta usando Projection?
Até da pra fazer com HQL, com Criteria não tenho certeza, mas não faz nenhum sentido isso.

R

Qual a regra do Fetch que vc esta usando?

Quando vc faz um .list() direto, ele carrega estes outros objetos?

xandevieira

Hj estou usando hql, estava vendo outras possibilidades, pois o hql tb cai num array de objetos selecionando somente campos especificos.
Estou tentando otimizar algumas tarefas. Pois nossas tabelas tem muitas colunas e não preciso de tudo.

xandevieira

Renato_natos:
Qual a regra do Fetch que vc esta usando?

Quando vc faz um .list() direto, ele carrega estes outros objetos?

Não carrega. Traz tudo nulo.

fbl.lucas

Entendi, mas no Projection você ta selecionando apenas os campos t.tituloPK.nuTitulo, t.cdDocumento, t.nuDocumento, d.deHistoricoCtb
Ou seja, você não seleciona o documento e credor…
Tente algo como abaixo, talvez não funcione com Criteria, mas no HQL funciona com certeza:

projection.add(Projections.property("t.documento"));
ou
projection.add(Projections.property("d").as("documento"));
xandevieira

fbl.lucas:
Entendi, mas no Projection você ta selecionando apenas os campos t.tituloPK.nuTitulo, t.cdDocumento, t.nuDocumento, d.deHistoricoCtb
Ou seja, você não seleciona o documento e credor…
Tente algo como abaixo, talvez não funcione com Criteria, mas no HQL funciona com certeza:

projection.add(Projections.property("t.documento")); ou projection.add(Projections.property("d").as("documento"));

Meu exemplo ficou incompleto.
Ele esta assim:

projectionList.add(Projections.property("t.tituloPK.nuTitulo")); projectionList.add(Projections.property("t.cdDocumento")); projectionList.add(Projections.property("t.nuDocumento")); projectionList.add(Projections.property("t.cdCredor")); projectionList.add(Projections.property("t.cdDocumento")); projectionList.add(Projections.property("t.nuDocumento")); projectionList.add(Projections.property("t.cdOrigem")); projectionList.add(Projections.property("t.deObservacao")); projectionList.add(Projections.property("t.flFormaPgCTB")); projectionList.add(Projections.property("t.vlValidacao")); projectionList.add(Projections.property("d.documentoPK.cdDocumento")); projectionList.add(Projections.property("d.deHistoricoCtb")); projectionList.add(Projections.property("d.nmDocumento")); projectionList.add(Projections.property("d.flFormaPgCTB")); projectionList.add(Projections.property("c.nmCredor")); projectionList.add(Projections.property("c.credorPK.cdCredor"));

Mas isso tende a aumentar, pq no momento estou so testando, haverão outros joins, tb com algumas colunas.

R

Vc poderia postar as suas classes que vc quer que venham preenchidas?

fbl.lucas

Então eu faria o seguinte talvez, criaria um construtor no Titulo que recebe os alias na mesma ordem em que foram adicionados no projectionList,
e utilizaria como result transformer o AliasToBeanConstructorResultTransformer, ele recebe como parametro o construtor que você criou que você pode ter acesso através do Titulo.class.getConstructor… algo assim, não é muito bonito mas eu ja usei isso e ajuda bastante, lembrando que deve existir o construtor default em Titulo também.
Dentro deste construtor que você cria, você iria instanciar os objetos.

xandevieira
Renato_natos:
Vc poderia postar as suas classes que vc quer que venham preenchidas?

Elas são grandes.
Mas vai lá.

TituloPK.java
    private Integer nuTitulo;
Titulo.java

@Element (name="tituloPK")
	private TituloPK tituloPK;
	@Element (name="cdEmpresa")
	private Integer cdEmpresa;
	@Element (name="cdCredor")
	private Integer cdCredor;
	@Element (name="cdDocumento")
	private String cdDocumento;
	@Element (name="nuDocumento")
	private String nuDocumento;
	@Element (name="dtEmissao")
	private Date dtEmissao;
	@Element (name="dtCompetencia")
	private Date dtCompetencia;
	@Element (name="dtCadastro")
	private Date dtCadastro;
	@Element (name="dtAlteracao", required=false)
	private Date dtAlteracao;
	private Integer nuTituloCRC;
	private String cdUsuario;
	private String cdUsuarioAlt;
	@Element (name="cdOrigem")
	private String cdOrigem;
	private Integer cdLocalAtual;
	@Element (name="deObservacao", required=false)
	private String deObservacao;
	private Integer nuRelatorioAdm;
	private Character flRelatorioAdm;
	private Character flEnviadoDoc;
	private Character flRelTaxaAdm;
	private Character flRecebidoDoc;
	private Integer nuLoteDocto;
	@Element (name="dtContabil", required=false)
	private Date dtContabil;
	@Element (name="flContabil")
	private Character flContabil;
	@Element (name="flFormaPgCTB")
	private Character flFormaPgCTB;
	private Integer nuLoteContabil;
	@Element (name="vlDesconto")
	private Double vlDesconto;
	@Element (name="vlValidacao")
	private Double vlValidacao;
	@Element (name="deDesconto", required=false)
	private String deDesconto;
	@Element (name="tpSerie", required=false)
	private String tpSerie;
	@Element (name="qtParcelas")
	private Integer qtParcelas;
	private Integer cdCCLoteFiscal;
	private Integer nuLoteFiscal;
	private String nuContrato;
	@Element (name="vlAcrescimo")
	private Double vlAcrescimo;

	private Integer cdOperacaoCtb;

	//ENTITY RELACIONAMENTOS
	private Documento documento;
	private Credor credor;
	private Empresa empresa;
	private Local local;
	private TipoPagamento tipoPagamento;
	private br.com.softplan.sienge.crc.Titulo tituloCrc;
	private Usuario usuario;
	private Usuario usuarioAlt;
	private InfoFiscal infoFiscal;
	private InfoFiscalImp infoFiscalImp;

	//LISTAS DE RELACIONAMENTOS

	@ElementList (name="impostoRetido",required=false)
	private List<ImpostoRetido> impostoRetido;

	private List<Parcela> parcelas;
	private List<ApropDepart> apropDepart;
	@ElementList (name="apropFin")
	private List<ApropFin> apropFin;
	@ElementList (name="apropObra")
	private List<ApropObra> apropObra;
	private List<ApropObraImp> apropObraImp;
	private List<ApropFinDesc> apropFinDesc;
	private List<AnexoTitulo> anexos;
	private List<LocalizacaoDoc> localizacoes;
	private List<ChequeHistBx> chequesHist;
	private List<DocLiberacaoME> docLiberacoes;
	private List<SaldoCredor> listSaldoCredor;
	private List<MovAdiantament> listMovAdiantament;
	private List<MovAdiantament> listMovAdiantamentVinculado;
CredorPK.java
private Integer cdCredor;
private CredorPK credorPK;
private String cdFornecedor;
	private String cdRepresentante;
	private String deCertificado;
	@Element(name = "deEmail", required = false)
	private String deEmail;

	private String deMSN;
	private String deSkype;
	private Date dtHomologacao;
	@Element(name = "flAtivo")
	private String flAtivo;
	@Element(name = "flFisJur")
	private String flFisJur;
	@Element(name = "flME")
	private String flME;
	@Element(name = "flApresGFIP")
	private String flApresGFIP;
	@Element(name = "flTipoConta")
	private Character flTipoConta;
	@Element(name = "flControlado")
	private String flControlado;
	@Element(name = "nmCredor")
	private String nmCredor;
	@Element(name = "nmFantasia", required = false)
	private String nmFantasia;
	@Element(name = "nuIdentidade", required = false)
	private String nuIdentidade;
	private String nuRamal;
	private String nuCMC;
	@Element(name = "nuCNPJ", required = false)
	private String nuCNPJ;
	@Element(name = "nuCPF", required = false)
	private String nuCPF;
	private String nuIncricaoEst;
	private String nuInscricaoMunic;
	private Double peComissao;
	private Integer qtPrazoMedEntr;
	@Element(name = "flAdiantamento")
	private Character flAdiantamento;
	@Element(name = "flFuncionario")
	private String flFuncionario;
	@Element(name = "flColabUsoPVD")
	private String flColabUsoPVD;
	@Element(name = "flColabUsoSGQ")
	private String flColabUsoSGQ;
	private String nuRegistro;
	private Date dtAdmissao;
	private Date dtDemissao;
	private String cdUsuarioSIE;
	private String cdUsuarioCad;
	private Integer cdCargoFuncao;
	private List<Afastamento> afastamentos;
	private List<AtividadeColab> listAtividadeColab;
	private AtividadeColab atividadeColabAux;

	private CompeteColab competeColab;

	private List<CredorCliente> credorCliente;
	private List<ClienteRep> clienteRep;

	private Usuario usuarioSIE;
	private CargoFuncao cargoFuncao;
	private Integer cdSetorObra;
	@Element(name = "telefone", required = false)
	private Telefone telefone;
	private Telefone fax;
	private String tpCredor;
	private Integer vlDeducao;
	private Double vlNota;
	@Element(name = "deObservacao", required = false)
	private String deObservacao;
	private String deSite;
	private String cdAuxiliar;
	private String cdBanco;
	private String dvAgencia;
	private String dvConta;
	private String dvDAC;
	private String nmAgencia;
	private String nmBanco;
	private String nuAgencia;
	private String nmFavorecido;
	private String nuCNPJFavorecido;
	private String nuCPFFavorecido;
	private String nuConta;
	private String cdImpRel;
	private Integer cdEmpresaTrabalha;

	private List<TelefoneCredor> telefones;
	private List<FormContCredor> formasContato;

	@Element(name = "flFornecedor", required = false)
	private String flFornecedor;
	@Element(name = "flCorretor", required = false)
	private String flCorretor;
	@Element(name = "flColaborador", required = false)
	private String flColaborador;
	@Element(name = "flOrgaoPublico", required = false)
	private String flOrgaoPublico;
	@Element(name = "municipio", required = false)
	private Municipio municipio;
	private TipoPagamento tipoPagamento;
	private Banco banco;
	@Element(name = "nuCreci", required = false)
	private String nuCreci;

	@Element(name = "flUtilizaPCR")
	private Character flUtilizaPCR;
	private String nmUsuarioPortal;
	private String nmSenhaPortal;

	private Colaborador colaborador;

	private Empresa empresaTrabalha;

	private List<AnexoCredor> anexoCredor;

	private Date dtCadastramento;
	private Date dtUltAlteracao;

Nem vou colocar as outras, como disse não preciso de tudo.
Haverão outras classes.

xandevieira

fbl.lucas:
Então eu faria o seguinte talvez, criaria um construtor no Titulo que recebe os alias na mesma ordem em que foram adicionados no projectionList,
e utilizaria como result transformer o AliasToBeanConstructorResultTransformer, ele recebe como parametro o construtor que você criou que você pode ter acesso através do Titulo.class.getConstructor… algo assim, não é muito bonito mas eu ja usei isso e ajuda bastante, lembrando que deve existir o construtor default em Titulo também.
Dentro deste construtor que você cria, você iria instanciar os objetos.

Pensei nisso tb, tanto q já fiz, o problema é que sempre q precisar selecionar outra coluna tenho q alterar o construtor.

fbl.lucas

é cara ta ficando muito complexo isso ai, o jeito vai ser trabalhar com o array mesmo, ou implementar um resultTransformer que ficaria mais elegante

R

Eu tenho a seguinte situação:

usuario
usuario_id
login
senha

tipo
tipo_id
tipo
usuario_id

onde, um usuario pode possuir varios tipos e eu precisava recuperar um ‘usuario’ por usuario_id com seus ‘tipos’ (sem o projections) e o hibernate montava algo deste tipo:

SELECT u.usuario_id, u.login, u.senha, t.tipo_id, t.tipo, t.usuario_id FROM usuario u left join tipo t on t.usuario_id = u.usuario_id WHERE u.usuario_id = ?

e as informações do usuario se repetiriam para cada ‘tipo’ que ele possuisse, no caso meu usuario tinha dois tipos e o resultado seria o seguinte:

u.usuario_id - u.login - u.senha - t.tipo_id - t.tipo - t.usuario_id
1 - guj - guj - 1 - a - 1
1 - guj - guj - 2 - b - 1

e o hibernate montava o objeto usuario com uma lista de tipos e eu era feliz.

Mas quando resolvi usar o projections as coisas complicaram. O projections é o código SQL que fica entre o ‘SELECT’ e o ‘FROM’.
No meu caso eu gostaria de recuperar apenas o usuario_id da tabela ‘usuario’ e o tipo_id da tabela ‘tipo’, fiz o projection para chegar neste resultado e a partir daí apenas erros aconteceram

Após varias pesquisas descobri que deveria fazer subconsultas para obter o resultado esperado, ou seja, primeiro eu recupero o usuario e depois recupero seus tipos.

Até o momento não consegui descobrir porque o hibernate se perde com o uso do projections.

xandevieira

tem ideia de como implementar?

fbl.lucas

tem ideia de como implementar?

Você pode se basear no codigo do AliasToBeanConstructorResultTransformer

public class AliasToBeanConstructorResultTransformer implements ResultTransformer {

	private Constructor constructor;

	public AliasToBeanConstructorResultTransformer(Constructor constructor) {
		this.constructor = constructor;
	}
	
	public Object transformTuple(Object[] tuple, String[] aliases) {
		try {
			return constructor.newInstance( tuple );
		}
		catch ( Exception e ) {
			throw new QueryException( 
					"could not instantiate: " + 
					constructor.getDeclaringClass().getName(), 
					e );
		}
	}

	public List transformList(List collection) {
		return collection;
	}

	
}
Criado 14 de fevereiro de 2012
Ultima resposta 15 de fev. de 2012
Respostas 16
Participantes 3