Как получить набор из Spring Data JPA NativeQuery? [приводит к NotReadablePropertyException] - PullRequest
0 голосов
/ 11 января 2019

Во-первых: я использую Spring-Boot Data JPA с Java 8.

В моей базе данных есть таблица, в которой моя сущность определяется следующим образом:

@Entity
@Table(name="ITEMHOURS")
public class ItemHoursEntity {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "ID")
    private int id;

    @Column(name = "YEAR", nullable = false)
    private String year;

    @Enumerated(EnumType.STRING)
    @Column(name = "STATE", nullable = false)
    private TypeEnum type;

    @Column(name = "HOURVALUE", nullable = false)
    private int hourValue = 0;

    @ManyToOne(cascade = CascadeType.MERGE)
    @JoinColumn(name = "ITEM_ID")
    private MyItem item;
//.. some more columns, getters, setters...
}

Теперь я получил следующий выбор, возвращающий эту структуру:

-----------------------
| YEAR | Value | Type |
-----------------------

@Query(value = "Select year as year, sum(hourvalue) as value, state as type from ITEMHOURS h where item_id = :item_id group by h.year, h.state", nativeQuery = true)
    public Optional<Collection<TotalValuesProjection>> getYearTotalsForStateByItem(@Param("item_id") int item_id);

Работает нормально у меня MySQL Workbench. Для результата я слышал, что мне нужно добиться, чтобы получить результат, отличный от значения по умолчанию ItemHoursEntity, с помощью проекции, поэтому я попытался создать следующее:

@Projection(types = { ItemHoursEntity.class })
public interface TotalValuesProjection {
    public String getYear();
    public int getValue();
    public HourTypeEnum getType();
}

Теперь в моем service -классе я пробую следующее:

@Override
public List<ExtendedDataPasser<String, Integer, String>> getTotalAndYearHourValuesForItem(int itemId) {

    Optional<Collection<TotalValuesProjection>> projectionOptional = this.hoursRepository.getYearTotalsForStateByItem(itemId);
    List<ExtendedDataPasser<String, Integer, String>> entityList = new ArrayList<ExtendedDataPasser<String, Integer, String>>();
    projectionOptional.orElseGet(() -> new ArrayList<TotalValuesProjection>()).forEach(entity -> {
        entityList.add(new ExtendedDataPasser<String, Integer, String>(entity.getYear(), entity.getValue(), entity.getType().toString()));
    });
    return entityList;
}

К сожалению, это приводит к следующей ошибке:

org.springframework.beans.NotReadablePropertyException: Invalid property 'year' of bean class [java.util.ArrayList]: Could not find field for property during fallback access!
        at org.springframework.data.util.DirectFieldAccessFallbackBeanWrapper.getPropertyValue(DirectFieldAccessFallbackBeanWrapper.java:58) ~[spring-data-commons-2.1.3.RELEASE.jar!/:2.1.3.RELEASE]
        at org.springframework.data.projection.PropertyAccessingMethodInterceptor.invoke(PropertyAccessingMethodInterceptor.java:73) ~[spring-data-commons-2.1.3.RELEASE.jar!/:2.1.3.RELEASE]
        at org.springframework.data.projection.ProjectingMethodInterceptor.invoke(ProjectingMethodInterceptor.java:64) ~[spring-data-commons-2.1.3.RELEASE.jar!/:2.1.3.RELEASE]
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.1.3.RELEASE.jar!/:5.1.3.RELEASE]
        at org.springframework.data.projection.ProxyProjectionFactory$TargetAwareMethodInterceptor.invoke(ProxyProjectionFactory.java:245) ~[spring-data-commons-2.1.3.RELEASE.jar!/:2.1.3.RELEASE]
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.1.3.RELEASE.jar!/:5.1.3.RELEASE]
        at org.springframework.data.projection.DefaultMethodInvokingMethodInterceptor.invoke(DefaultMethodInvokingMethodInterceptor.java:59) ~[spring-data-commons-2.1.3.RELEASE.jar!/:2.1.3.RELEASE]
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.1.3.RELEASE.jar!/:5.1.3.RELEASE]
        at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:212) ~[spring-aop-5.1.3.RELEASE.jar!/:5.1.3.RELEASE]
        at com.sun.proxy.$Proxy133.getYear(Unknown Source) ~[na:na]

Может быть, поможет полный скриншот ошибки:

enter image description here

Это исключение, когда я пытаюсь получить доступ к year -атрибуту в первую очередь, это ошибка: (почти такая же, просто year вместо hourValue)

enter image description here

Я что-то связал с отображением проекции на сущность?

Ответы [ 2 ]

0 голосов
/ 11 января 2019

Попробуйте этот код,

@Query(value = "Select year, sum(hourvalue) as value, state as type from ITEMHOURS h where item_id = :item_id group by h.year, h.state", nativeQuery = true)
    public Optional<Collection<TotalValuesProjection>> getYearTotalsForStateByItem(@Param("item_id") int item_id);

если возникнут проблемы сообщите !!

0 голосов
/ 11 января 2019

Это не твердое решение, а просто мысли вслух. В основном это зависит от версий СУБД и Hibernate, но в некоторых случаях такое исключение может возникнуть из-за учета регистра, поэтому попробуйте добавить к псевдонимам кавычки в собственном запросе и псевдоним таблицы к именам столбцов следующим образом:

@Query(value = "Select h.year as \"year\", sum(h.hourValue) as \"value\", h.state as \"type\" from ITEMHOURS h where h.item_id = :item_id group by h.year, h.state", nativeQuery = true)
    public Optional<Collection<TotalValuesProjection>> getYearTotalsForStateByItem(@Param("item_id") int item_id);

UPD изменить hourValue свойство в соответствии с соглашением Java - 'h' должно быть в верхнем регистре

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...