select firstName, lastName from Employee
query.setResultTransformer(Transformers.aliasToBean(MyResults.class));
Non è possibile utilizzare sopra il codice con Hibernate 5 e Hibernate 4 (almeno Hibernate 4.3.6.Final), a causa di un'eccezione
java.lang.ClassCastException: com.github.fluent.hibernate.request.persistent.UserDto cannot be cast to java.util.Map
at org.hibernate.property.access.internal.PropertyAccessMapImpl$SetterImpl.set(PropertyAccessMapImpl.java:102)
Il problema è che Hibernate converte alias per i nomi di colonna in maiuscolo - firstName
diventa FIRSTNAME
. E cercare di trovare un getter con il nome getFIRSTNAME()
, e Setter setFIRSTNAME()
nel DTO
utilizzando tali strategie
PropertyAccessStrategyChainedImpl propertyAccessStrategy = new PropertyAccessStrategyChainedImpl(
PropertyAccessStrategyBasicImpl.INSTANCE,
PropertyAccessStrategyFieldImpl.INSTANCE,
PropertyAccessStrategyMapImpl.INSTANCE
);
Solo PropertyAccessStrategyMapImpl.INSTANCE
abiti, a parere di Hibernate, bene. Quindi dopo prova a fare la conversione (Map)MyResults
.
public void set(Object target, Object value, SessionFactoryImplementor factory) {
((Map) target).put(propertyName, value);
}
Non so, si tratta di un bug o di una funzionalità.
Come risolvere
Utilizzando gli alias con le citazioni
public class Results {
private String firstName;
private String lastName;
public String getFirstName() {
return firstName;
}
public String getLastName() {
return lastName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
}
String sql = "select firstName as \"firstName\",
lastName as \"lastName\" from Employee";
List<Results> employees = session.createSQLQuery(sql).setResultTransformer(
Transformers.aliasToBean(Results.class)).list();
Utilizzando un risultato personalizzato trasformatore
Un altro modo per risolvere il problema - utilizzando un trasformatore risultato che ignora nome dei metodi caso (trattare getFirstName()
come getFIRSTNAME()
). Puoi scrivere il tuo o usare FluentHibernateResultTransformer. Non è necessario utilizzare virgolette e alias (se i nomi delle colonne sono uguali ai nomi DTO).
Basta scaricare la libreria dalla pagina del progetto (non necessita di ulteriori giare): fluent-hibernate.
String sql = "select firstName, lastName from Employee";
List<Results> employees = session.createSQLQuery(sql)
.setResultTransformer(new FluentHibernateResultTransformer(Results.class))
.list();
Questo trasformatore può essere utilizzato per le proiezioni nidificati troppo: How to transform a flat result set using Hibernate
divertente, posso riprodurre il problema con Hibernate 5.1. Il trasformatore 'Transformers.aliasToBean (CatDTO.class)' non funziona. Ho appena provato con il mio trasformatore prima :) Cerca di capire perché. –
È molto più divertente, avevo ragione con gli alias. Vedi la mia risposta: http://stackoverflow.com/a/37423885/3405171 –