Use menos colunas na consulta SQL através de projeções do Hibernate em entidade com relação ManyToOne

StackOverflow https://stackoverflow.com/questions/1618394

Pergunta

Eu estou tentando construir um SQL menor, para evitar o "SELECT * FROM A" que está sendo configuração por padrão para Critérios de hibernação.

Se eu usar campos simples (nenhuma relação), através de "Transformers", que tenho consegue ter esse SQL:

select description, weight from Dog;

Oi, eu tenho esta Entidade:

@Entity
public class Dog
{
   Long id;
   String description;
   Double weight;
   @ManyToOne(fetch = FetchType.LAZY)
   @JoinColumn(name = "person_id", nullable = false)
   Person owner;
}

@Entity
public class Person
{
   Long id;
   String name;
   Double height;
   Date birthDate;
}

Meu objetivo é ter o seguinte:

select description, weight, owner.name from Dog

Eu tentei isso com com critérios (e subcritérios):

Criteria dogCriteria = sess.createCriteria(Dog.class);
ProjectionList proList = Projections.projectionList();
proList.add(Projections.property("description"), description);
proList.add(Projections.property("weight"), weigth);
dogCriteria.setProjection(proList);

Criteria personCriteria = dogCriteria.createCriteria("owner");
ProjectionList ownerProList = Projections.projectionList();
ownerProList.add(Projections.property("name"), description);    
dogCriteria.setProjection(ownerProList);  //After this line,  debugger shows that the
                                          //projection on dogCriteria gets overriden
                                          //and the query fails, because "name" is
                                          //not a field of Dog entity.

Como devo tomar Projeções, para obter um SQL menor, menos colunas? Agradecemos antecipadamente.

Foi útil?

Solução

Em primeiro lugar,

select description, weight, owner.name from Dog

Não é SQL válido. Teria que ser algo como

select description, weight, Person.name
 from Dog join Person on Dog.person_id = Person.id

em seu lugar. Em segundo lugar, por quê? Embora seja possível fazer o que quiser (veja abaixo), é extremamente detalhado para fazê-lo através Criteria API e você não ganha nada para mostrar para ele. Poupança em transferência de dados para um par de colunas são insignificantes a menos que disse colunas são enormes bolhas ou você está selecionando centenas de milhares de registros. Em ambos os casos há melhores maneiras de lidar com esta questão.

Anywho, para fazer o que quiser para os critérios, você precisa para se juntar a tabela vinculada (Pessoa) via alias e especificar a projeção em principais critérios utilizando a referida apelido:

Criteria criteria = session.createCriteria(Dog.class, "dog")
 .createAlias("owner", "own")
 .setProjection( Projections.projectionList()
   .add(Projections.property("dog.description"))
   .add(Projections.property("dog.weight"))
   .add(Projections.property("own.name"))
 );

Há uma descrição e um exemplo do acima em Projeções Critérios documentação . Tenha em mente que, quando executado, os critérios acima iria retornar uma lista de matrizes de objetos. Você precisa especificar um ResultTransformer , a fim de ter resultados convertidos em objetos reais.

Outras dicas

Eu não tentei ainda por mim, mas eu acho que você também pode usar outro construtor em sua Entidade (Pojo) e passar as colunas lá. Consulte https://www.thoughts-on-java.org/hibernate- melhores práticas / capítulo "1,2 Pojo" para uma instrução detalhada. Altough para mim ainda não está claro se isso também funciona para relações ManyToOne também. Vou ter uma tentativa.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top