Проекция на основе интерфейса - метод get, выдающий исключение, если тип возвращаемого значения - java.sql.Timestamp. - PullRequest
3 голосов
/ 06 июня 2019

Я использую пружинную загрузочную пластинку 2.2.0.BUILD-SNAPSHOT с Spirng JPA. Мне нужно использовать сложный SQL с группой, в некоторых я использую собственный запрос с проекцией на основе интерфейса, я могу восстановить все поля, но получаю исключение для типа возврата java.sql.Timestamp

Пример: Моя сущность класс

@Entity
@Table(name = "trade")
public class Trade {

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "trade_id")
private long tradeId;

@Column(name = "symbol")
private String symbol;

@Column(name = "exchange")
private String exchange;

@Column(name = "segment")
private String segment;

@Column(name = "clinet_trade_id")
private long clientTradeId;

@Column(name = "order_id")
private long orderId;

@Column(name = "price")
private double price;

@Column(name = "sell_type")
private String tradeType;

@Column(name = "quantity")
private int quantity;

@Column(name = "trade_date_time")
private Timestamp tradeDateTime;
}

Интерфейс репозитория с интерфейсом проецирования

@Repository("TradeRepository")
public interface TradeRepository extends JpaRepository<Trade, Long> {


// projection

//https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#projections
//Interface-based Projections
//https://www.baeldung.com/spring-data-jpa-projections

@Query(value = "select symbol,date(trade_date_time) as trade_date_time , sum(quantity) as quantity , sum(quantity*price) as price  from trade where sell_type ='sell' \n" + 
        "and trader_date > ?1  and trader_date < ?2 and user_id= ?3 " + 
        "group by symbol, date(trade_date_time) " + 
        "order by symbol, date(trade_date_time) ", nativeQuery = true)
 public List<TradeView> findByNativeQuery(Timestamp fromdate, Timestamp toDate, int userId);

public static interface TradeView {
     public String getSymbol();
     public Timestamp getTradeDateTime();
     public int getQuantity();
     public double getPrice();
  }


}

Здесь я получаю исключение для метода getTradeDateTime()

Трассировка исключения

java.lang.IllegalArgumentException: Projection type must be an interface!
at org.springframework.util.Assert.isTrue(Assert.java:118)
at org.springframework.data.projection.ProxyProjectionFactory.createProjection(ProxyProjectionFactory.java:100)
at org.springframework.data.projection.SpelAwareProxyProjectionFactory.createProjection(SpelAwareProxyProjectionFactory.java:45)
at org.springframework.data.projection.ProjectingMethodInterceptor.getProjection(ProjectingMethodInterceptor.java:131)
at org.springframework.data.projection.ProjectingMethodInterceptor.invoke(ProjectingMethodInterceptor.java:80)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.data.projection.ProxyProjectionFactory$TargetAwareMethodInterceptor.invoke(ProxyProjectionFactory.java:245)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.data.projection.DefaultMethodInvokingMethodInterceptor.invoke(DefaultMethodInvokingMethodInterceptor.java:59)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:212)
at com.sun.proxy.$Proxy123.getTradeDateTime(Unknown Source)
at org.cet.stockAnalysis.repository.TradeRepositoryTest.findAllSaleTradeByDateTest(TradeRepositoryTest.java:45)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.springframework.test.context.junit4.statements.RunBeforeTestExecutionCallbacks.evaluate(RunBeforeTestExecutionCallbacks.java:74)
at org.springframework.test.context.junit4.statements.RunAfterTestExecutionCallbacks.evaluate(RunAfterTestExecutionCallbacks.java:84)
at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75)
at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86)
at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:251)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:97)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:190)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:89)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:41)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:541)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:763)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:463)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:209)

Может ли кто-нибудь подсказать мне, что можно сделать, у меня есть одно решение - изменить имя столбца БД, чтобы оно совпадало с именем поля сущности, но я чувствую, что это неправильно, должно быть какое-то решение для этого.

Отладка снимка экрана

enter image description here

Примечание: я получаю исключение при вызове метода get для чтения значения, и в то же время он собирается перейти к строке 100 ProxyProjectionFactory и в то время идентификатору типа java.sql.Timestamp и получить исключение

Scren shot

enter image description here

Тестовый класс Junit

@RunWith(SpringRunner.class)
@DataJpaTest
@AutoConfigureTestDatabase(replace=Replace.NONE)
public class TradeRepositoryTest {

@Autowired
TradeRepository tradeRepository;

@Test
public void findAllSaleTradeByDateTest() {
    Date fromdate = new GregorianCalendar(2019, Calendar.FEBRUARY, 1).getTime();
    Date todate = new GregorianCalendar(2019, Calendar.MARCH, 31).getTime();

    Timestamp fromTimestamp= new Timestamp(fromdate.getTime());
    Timestamp toTimestamp= new Timestamp(todate.getTime());

    User user = new User();
    user.setId(1);
    List<TradeView> tradeviews =tradeRepository.findByNativeQuery(fromTimestamp, toTimestamp, 1);
    System.out.println(tradeviews.get(0).getSymbol());
    System.out.println(tradeviews.get(0).getPrice());
    System.out.println(tradeviews.get(0).getTradeDateTime() +" >>>>>> ");
    System.out.println(tradeviews.get(0).getQuantity());


    assertNotNull(tradeviews);
}

}

Edit:

С предложением Саймона я изменяю тип возвращаемого интерфейса на java.sql.Date form java.sql.Timestamp, и он работает нормально, так как мой собственный тип возвращаемого значения sql был date, потому что использовалась функция даты

Следовательно, изменение названия вопроса и деталей

1 Ответ

3 голосов
/ 06 июня 2019

Просто нам псевдонимы соответствуют имена в вашем интерфейсе.Не используйте _, но tradeDateTime:

@Query(value = "select symbol, date(trade_date_time) as tradeDateTime, sum(quantity) as quantity , sum(quantity*price) as price  from trade where sell_type ='sell' \n" + 
    "and trader_date > ?1  and trader_date < ?2 and user_id= ?3 " + 
    "group by symbol, date(trade_date_time) " + 
    "order by symbol, date(trade_date_time) ", nativeQuery = true)

Причина: отображение столбцов в вашей сущности не учитывается при использовании собственных запросов и проекции интерфейса.

Также убедитесь, чточтобы у вас были правильные типы возвращаемых данных интерфейса!

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