2013-06-28 8 views
11

1 2: (. Tabelle *) wählen/(alle Spalte) OK istHibernate SQL Query Ergebnis Mapping/Objekt umwandeln/Klasse/Bean

String sql = "select t_student.* from t_student"; 
//String sql = "select t_student.id,t_student.name,... from t_student"; //select all column 
SQLQuery query = session.createSQLQuery(sql); 
query.addEntity(Student.class);//or query.addEntity("alias", Student.class); 
//query.list();[[email protected], [email protected], [email protected]] 
query.setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP); //or other transformer 
query.list(); //[{Student(or alias)[email protected]},{[email protected]}] 

3: Wählen Sie eine Spalte (nicht alle), ist Fehler

Ich möchte "3", um OK zu arbeiten, und lassen Sie das Ergebnis zu Student.class zugeordnet werden.
Wie: Student [ID =?, Name =?, Geschlecht = ?, (andere Feld sind Null/Standard)]
Ich habe keine Ahnung für diesen Fehler, hilf mir bitte!

+1

warum sql Abfrage verwenden? Wann können Sie hql oder Kriterien verwenden? Sie setzen 'hql' anstelle von' sql' in 3 ein Fehler: P – nachokk

+1

haha! Ich zeige nur ein Beispiel.In der Tat, einige Geschäfte müssen von SQL implementiert werden. – YETI

Antwort

3

Es gibt nur zwei Möglichkeiten.

Sie können das erste oder zweite Snippet verwenden. Laut Hibernate-Dokumentation müssen Sie 2nd bevorzugen.

Sie können nur eine Liste von Objekt Arrays erhalten, wie folgt aus:

String sql = "select name, sex from t_student"; 
SQLQuery query = session.createSQLQuery(sql); 
query.addScalar("name", StringType.INSTANCE); 
query.addScalar("sex", StringType.INSTANCE); 
query.list(); 
+0

Danke. Benutze query.setResultTransformer ({custom transformer}) nach addScalar, kann in die Student.class umwandeln, aber ich will es nicht so. – YETI

+0

Ich möchte, dass es eine Objektinstanz von Student ist, ist jemand bekannt? – YETI

17

Sie können weiter gehen und .setResultTransformer(Transformers.aliasToBean(YOUR_DTO.class)); hinzufügen und automatisch dto Objekt zu Ihrer benutzerdefinierten Karte, siehe auch Returning non-managed entities.

Zum Beispiel:

public List<MessageExtDto> getMessagesForProfile2(Long userProfileId) { 
    Query query = getSession().createSQLQuery(" " 
      + " select a.*, b.* " 
      + " from messageVO AS a " 
      + " INNER JOIN (SELECT max(id) AS id, count(*) AS count FROM messageVO GROUP BY messageConversation_id) as b ON a.id = b.id " 
      + " where a.id > 0 " 
      + " ") 
      .addScalar("id", new LongType()) 
      .addScalar("message", new StringType()) 
      ......... your mappings 
      .setResultTransformer(Transformers.aliasToBean(MessageExtDto.class)); 

    List<MessageExtDto> list = query.list(); 
    return list; 
} 
+3

Es sollte nützlich sein, aber ich bin so faul, ich dachte, dass es automatisch umgewandelt werden kann. – YETI

3

ich will "3" ok arbeiten, und das Ergebnis lassen kann

zu Student.class zugeordnet werden, die möglich ist, mit
Query createNativeQuery(String sqlString, String resultSetMapping)

Im zweiten Argument können Sie den Namen der Ergebniszuordnung angeben. Zum Beispiel:

1) Lassen Sie sich eine Student Einheit betrachtet, ist die Magie geht in der SqlResultSetMapping Anmerkung sein:

import javax.persistence.Entity; 
import javax.persistence.SqlResultSetMapping; 
import javax.persistence.Table; 

@Entity 
@Table(name = "student") 
@SqlResultSetMapping(name = "STUDENT_MAPPING", classes = {@ConstructorResult(
    targetClass = Student.class, columns = { 
     @ColumnResult(name = "name"), 
     @ColumnResult(name = "address") 
})}) 
public class Student implements Serializable { 
    private String name; 
    private String address; 

    /* Constructor for the result mapping; the key is the order of the args*/ 
    public Student(String aName, String anAddress) { 
     this.name = aName; 
     this.address = anAddress; 
    } 

    // the rest of the entity 
} 

2) Jetzt können Sie eine Abfrage ausführen, die Ergebnisse werden von STUDENT_MAPPING abgebildet werden Logik:

String query = "SELECT s FROM student s"; 
String mapping = "STUDENT_MAPPING"; 
Query query = myEntityManager.createNativeQuery(query, mapping); 
@SuppressWarnings("unchecked") 
List<Student> students = query.getResultList(); 
for (Student s : students) { 
    s.getName(); // ... 
} 

Hinweis: ich denke, es ist nicht möglich, die nicht markiert Warnung zu vermeiden.

0

Ich hatte dasselbe Problem auf HQL-Abfrage. Ich löste das Problem, indem ich den Transformator änderte.

Das Problem führte dazu, dass der geschriebene Code als Map transformiert wurde. Aber es ist nicht für Alias ​​Bean geeignet. Sie können den Fehlercode unten sehen. Der Code, der in die Umwandlung geschrieben wird, wird als Karte ausgegeben und ein neues Feld in die Karte eingefügt.

Klasse: org.hibernate.property.access.internal.PropertyAccessMapImpl.SetterImpl m Methode: set

@Override 
    @SuppressWarnings("unchecked") 
    public void set(Object target, Object value, SessionFactoryImplementor factory) { 
     ((Map) target).put(propertyName, value); 
    } 

Ich löste das Problem, den Transformator zu duplizieren und den Code zu ändern.

Sie können den Code im Projekt sehen.

-Link: https://github.com/robeio/robe/blob/DW1.0-migration/robe-hibernate/src/main/java/io/robe/hibernate/criteria/impl/hql/AliasToBeanResultTransformer.java

Klasse:

import java.lang.reflect.Field; 
import java.util.Map; 

import io.robe.hibernate.criteria.api.query.SearchQuery; 
import org.hibernate.HibernateException; 
import org.hibernate.transform.AliasedTupleSubsetResultTransformer; 
import org.slf4j.Logger; 
import org.slf4j.LoggerFactory; 


public class AliasToBeanResultTransformer extends AliasedTupleSubsetResultTransformer { 

    private static final Logger LOGGER = LoggerFactory.getLogger(AliasToBeanResultTransformer.class); 

    private final Class resultClass; 

    // Holds fields of Transform Class as Map. Key is name of field. 
    private Map<String, Field> fieldMap; 

    public AliasToBeanResultTransformer(Class resultClass) { 
     if (resultClass == null) { 
      throw new IllegalArgumentException("resultClass cannot be null"); 
     } 
     fieldMap = SearchQuery.CacheFields.getCachedFields(resultClass); 
     this.resultClass = resultClass; 
    } 

    @Override 
    public boolean isTransformedValueATupleElement(String[] aliases, int tupleLength) { 
     return false; 
    } 

    @Override 
    public Object transformTuple(Object[] tuple, String[] aliases) { 
     Object result; 
     try { 
      result = resultClass.newInstance(); 
      for (int i = 0; i < aliases.length; i++) { 
       String name = aliases[i]; 
       Field field = fieldMap.get(name); 

       if(field == null) { 
        LOGGER.error(name + " field not found in " + resultClass.getName() + " class ! "); 
        continue; 
       } 
       field.set(result, tuple[i]); 
      } 
     } 
     catch (InstantiationException e) { 
      throw new HibernateException("Could not instantiate resultclass: " + resultClass.getName()); 
     } catch (IllegalAccessException e) { 
      throw new HibernateException("Could not instantiate resultclass: " + resultClass.getName()); 
     } 

     return result; 
    } 
} 

Nach neuen Transformer erstellt Sie wie unten verwenden können.

query.setResultTransformer(new AliasToBeanResultTransformer(YOUR_DTO.class));