我正在将Spring Boot strater 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)
有人可以指导我做什么吗,我有一个解决方案是更改数据库列名称以与实体文件名匹配,但是我觉得这是不对的,对此必须有一些解决方案。
调试屏幕截图
注意:我在调用getter方法读取值时得到了异常,这时它也将到达ProxyProjectionFactory行号100,并且当时是id为java.sql.Timestamp的类型并产生异常< / p>
射击镜头
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);
}
}
编辑:
在Simon的建议下,我将接口返回类型从java.sql.Timestamp更改为java.sql.Date,由于使用了日期功能,我的本机sql返回类型为date,因此可以正常工作
因此更改问题标题和详细信息
答案 0 :(得分:3)
我们简单地将匹配名称作为界面中的名称的别名。不要使用_,但要使用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)
原因:在使用本机查询和接口投影时,不会考虑您实体中的列映射。
还请确保您具有接口的正确返回类型!