19

1 2: select (table.*)/(all column) でOK

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();[Student@..., Student@..., Student@...]
query.setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP); //or other transformer
query.list(); //[{Student(or alias)=Student@...},{Student=Student@...}]

3: 一部の列 (すべてではない) を選択すると、エラーになります

String sql = "select t_student.id,t_student.name.t_student.sex from t_student";
SQLQuery query = session.createSQLQuery(sql);
query.addEntity(Student.class);
query.setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
query.list(); //Exception:invalid column/no column

「3」が正常に機能し、結果を Student.class にマップできるようにしたい。
例: Student[id=?, name=?, sex=?, (他のフィールドは null/default)]
このエラーの意味がわかりません。助けてください!

4

5 に答える 5

25

さらに進んで追加 .setResultTransformer(Transformers.aliasToBean(YOUR_DTO.class)); し、それをカスタム dto オブジェクトに自動的にマップすることができます。管理されていないエンティティを返すも参照してください。

例えば:

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;
}
于 2014-02-13T15:03:39.417 に答える
3

2つの方法しかありません。

1 番目または 2 番目のスニペットを使用できます。Hibernate のドキュメントによると、2nd を優先する必要があります。

次のように、オブジェクト配列のリストだけを取得できます。

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();
于 2013-06-28T04:13:21.833 に答える
1

HQL クエリでも同じ問題が発生しました。トランス交換で解決しました。

この問題により、記述されたコードが Map として変換されました。ただし、Alias Bean には適していません。エラーコードは以下で確認できます。結果をマップとしてキャストし、新しいフィールドをマップに配置するために記述されたコード。

クラス: org.hibernate.property.access.internal.PropertyAccessMapImpl.SetterImpl m メソッド: set

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

トランスを複製してコードを変更することで問題を解決しました。

プロジェクト内のコードを確認できます。

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

クラス:

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;
    }
}

新しい Transformer を作成したら、以下のように使用できます。

query.setResultTransformer(new AliasToBeanResultTransformer(YOUR_DTO.class));
于 2016-12-07T12:37:33.820 に答える
0

自動的にマッピングできます:

  1. あなたのモデル Student.java

    public class Student { プライベート文字列名; プライベート文字列アドレス; }

  2. リポジトリ

    String sql = "Select * from Student"; クエリ query = em.createNativeQuery(sql, Student.class); リスト ls = query.getResultList();

  • そのため、結果が Student クラスに自動的にマップされます
于 2021-04-24T05:24:21.670 に答える