Hibernate Native Query с 5.2.10

В Hibernate ‹ 5.2 можно было использовать общие SQL-запросы, такие как

String sql = "select a, b, sum (c) csum from a group by a, b";
SQLQuery q = session.createSqlQuery (sql);
q
    .addScalar ("a", IntegerType.INSTANCE)
    .addScalar ("b", IntegerType.INSTANCE)
    .addScalar ("csum", IntegerType.INSTANCE);
q.setResultTransformer (new AliasToBeanResultTransformer (RankingModel.class));
List<RankingModel> results = q.list ();

Где RankingModel выглядит так:

public class RankingModel
{
    public int a, b, csum;
}

Однако в версии 5.2 все addScalar(), setResultTransformer() устарели, вместо них рекомендуется использовать session.createNativeQuery(). Ближайший эквивалент вышеизложенному у меня есть:

String sql = "select a, b, sum (c) csum from a group by a, b";
NativeQuery<RankingModel> q = session.createNativeQuery (sql, RankingModel.class);
List<RankingModel> results = q.list ();

Однако этот код не работает с:

org.hibernate.MappingException: Unknown entity: ... RankingModel] with root cause
org.hibernate.MappingException: Unknown entity: ... RankingModel
    at org.hibernate.metamodel.internal.MetamodelImpl.entityPersister(MetamodelImpl.java:620)
    at org.hibernate.engine.spi.SessionFactoryImplementor.getEntityPersister(SessionFactoryImplementor.java:335)
    at org.hibernate.loader.custom.sql.SQLQueryReturnProcessor.getSQLLoadable(SQLQueryReturnProcessor.java:358)
    at org.hibernate.loader.custom.sql.SQLQueryReturnProcessor.processRootReturn(SQLQueryReturnProcessor.java:411)
    at org.hibernate.loader.custom.sql.SQLQueryReturnProcessor.processReturn(SQLQueryReturnProcessor.java:378)
    at org.hibernate.loader.custom.sql.SQLQueryReturnProcessor.process(SQLQueryReturnProcessor.java:180)
    at org.hibernate.loader.custom.sql.SQLCustomQuery.<init>(SQLCustomQuery.java:71)
    at org.hibernate.engine.query.internal.NativeQueryInterpreterStandardImpl.createQueryPlan(NativeQueryInterpreterStandardImpl.java:70)
    at org.hibernate.engine.query.spi.QueryPlanCache.getNativeSQLQueryPlan(QueryPlanCache.java:213)
    at org.hibernate.internal.AbstractSharedSessionContract.getNativeQueryPlan(AbstractSharedSessionContract.java:550)
    at org.hibernate.internal.AbstractSharedSessionContract.list(AbstractSharedSessionContract.java:992)
    at org.hibernate.query.internal.NativeQueryImpl.doList(NativeQueryImpl.java:148)

Кто-нибудь знает, что мне не хватает?


person Jonathan    schedule 09.05.2017    source источник
comment
Можешь опубликовать свой RankingModel.java? Кажется, что этот объект не имеет a, b и sum в качестве переменных экземпляра.   -  person lxcky    schedule 10.05.2017
comment
В javadoc после предупреждения об устаревании есть этот комментарий: @todo develop a new approach to result transformers... На данный момент может не быть определенного пути миграции. Ближайшая концепция - ResultSetMapping, но я не уверен, что она такая же гибкая, как преобразователи набора результатов.   -  person Thierry    schedule 10.05.2017


Ответы (3)


Вы можете попробовать исправить с помощью

String sql = "select a, b, sum (c) csum from a group by a, b";
NativeQuery<?> q = session.createNativeQuery (sql);
List<RankingModel> results = (List<RankingModel>)q.list ();

Это будет работать, но в IDE будет выдано предупреждение.

Or

String sql = "select a, b, sum (c) csum from a group by a, b";
    NativeQuery<?> q = session.createNativeQuery (sql).addSynchronizedEntityClass( RankingModel.class );
    List<RankingModel> results = (List<RankingModel>)q.list ();
person rajadilipkolli    schedule 02.08.2017
comment
Неа. Я разговаривал с разработчиками, и это TODO. - person Jonathan; 03.08.2017

Чтобы указать Hibernate использовать пользовательские классы сущностей (компонентов данных), такие как RankingModel.java, вы должны аннотировать каждый такой класс с помощью @Entity и каждый назначаемый столбец (поле) с помощью @Id или @Column в соответствии со спецификацией JPA. Фактически, Hibernate делает все возможное, чтобы соблюдать контракт JPA 2.0 и поддерживает все соответствующие аннотации Java из пакета javax.persistence.

При этом убедитесь, что каждый класс объектов имеет поле уникального идентификатора, как указано в исключение гибернации: org.hibernate.AnnotationException: идентификатор не указан для объекта: com..domain.idea.MAE_MFEView

Вот как должен выглядеть ваш класс сущности:

@Entity
public class RankingModel
{
    @Id
    public int id;

    @Column
    public int a;

    @Column
    public int b;

    @Column
    public int csum;
}

Если сущность должна быть сохранена в базе данных, класс также должен быть аннотирован с помощью @Table. Это явно сообщает Hibernate, какую таблицу базы данных использовать для сохранения сущности. Я считаю, что только для получения данных аннотация не нужна.

Наконец, скажите Hibernate, чтобы он действительно искал все (аннотированные) классы сущностей. Этого можно добиться, сославшись на них из hbm.xml или, для пуристов Java, таких как я, перечислив пакеты Java для сканирования в качестве аргумента конструктору LocalSessionFactoryBean, как хорошо объяснено в Как сканировать пакеты на наличие объектов Hibernate вместо использования hbm.xml?

person leonidos79    schedule 09.05.2018
comment
Добавление @Entity создает физическую таблицу, которая мне не нужна. - person Jonathan; 24.12.2019

person    schedule
comment
что, если я просто хочу HashMap с псевдонимом вместо объекта класса Entity - person user1735921; 11.12.2018