Spring Data JPA 接收参数值 [2] 与预期类型 [java.lang.String (n/a)] 不匹配
Spring Data JPA Receiving parameter value [2] did not match expected type [java.lang.String (n/a)]
我知道这里已经提出了类似的问题,但相信我,我做了研究,尝试了很多不同的方法,但还没有运气。
我的配置:Spring Data JPA(休眠,H2 DB),上面的REST层,并有一个AngularJS客户端发出请求。
休息路径:
@RequestMapping("/search/{destinationId}/{arrivalId}/{departureTime}/{arrivalTime}/{numberOfPassengers}")
public List<Flight> getFlightsWithCriteria(@PathVariable String destinationId,
@PathVariable String arrivalId,
@PathVariable String departureTime,
@PathVariable String arrivalTime,
@PathVariable Integer numberOfPassengers) { }
我按如下方式调用服务:
/search/2/1/2016-08-15T21:00:00.000Z/2016-08-15T21:00:00.000Z/2
顺便说一下,departureTime
对象是数据库上的TIMESTAMP
,测试数据的格式为 2016-05-16 17:30:00.0
然后将日期解析为与数据库匹配的合适格式:
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date departureDate = sdf.parse(departureTime);
String formattedTime = dateFormat.format(departureDate);
然后在我的查询中使用此格式化时间参数,如下所示:
flights = (List<Flight>) entityManager
.createQuery("SELECT f FROM Flight f WHERE f.departureTerminal = :destination AND f.arrivalTerminal = :arrival AND f.departureTime <= :departureDate AND f.numberOfSeatsAvailable <= :numberOfPassengers")
.setParameter("destination", destination)
.setParameter("arrival", arrival)
.setParameter("departureDate", newDate)
.setParameter("numberOfPassengers", numberOfPassengers).getResultList();
然后我当然会收到:
java.lang.IllegalArgumentException: Parameter value [2] did not match expected type [java.lang.String (n/a)]
鉴于这些,您可能会说为什么我将查询中的String
发送到TIMESTAMP
对象,到目前为止我已经尝试过:
- 在查询中发送
String
, - 在查询中发送
Date
, - 在查询中发送
Date
TemporalType.TIMESTAMP
, @PathParam
使用@DateFormat
- 将日期类型的整个实体模型更改为
String
,并在上面一次又一次地尝试
..我已经为此挠了几个小时,但还没有解决方案。
你能看看我的代码并指出我做错了什么吗?
谢谢
尝试通过在适当的位置添加括号来明确查询操作数的分组,以帮助您进行逻辑和调试,例如下面
flights = (List<Flight>) entityManager
.createQuery("SELECT f FROM Flight f WHERE f.departureTerminal = :destination AND f.arrivalTerminal = :arrival AND (f.departureTime <= :departureDate) AND (f.numberOfSeatsAvailable <= :numberOfPassengers)")
.setParameter("destination", destination)
.setParameter("arrival", arrival)
.setParameter("departureDate", newDate)
.setParameter("numberOfPassengers", numberOfPassengers).getResultList();
另一个想法,尝试传递 1 个参数,然后调整您的请求以提供 1 个参数,然后继续第二个参数,依此类推。这将准确指出哪个参数有问题。
一旦你发现了罪魁祸首,现在通过传递作为唯一的请求参数来修复它,将问题简化为该参数。
更新日期(我的解决方案):
我对你的代码又有一次破解,查询很好。我怀疑这是您的输入是问题,例如您报告的异常。这是我为测试所做的,如果这有助于您的测试,则与您的查询类似。
飞行测试.java
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = { TestH2DatabaseConfiguration.class }, loader = AnnotationConfigContextLoader.class)
public class FlightTest extends AbstractTransactionalJUnit4SpringContextTests {
final static Logger log = LoggerFactory.getLogger(FlightTest.class);
@Autowired
@Qualifier("entityManagerFactory")
EntityManagerFactory entityManagerFactory;
@Test
@SuppressWarnings("unchecked")
public void test() throws ParseException {
assertNotNull(entityManagerFactory);
EntityManager entityManager = entityManagerFactory.createEntityManager();
assertNotNull(entityManager);
List<Flight> flights = (List<Flight>) entityManager.createQuery("FROM Flight").getResultList();
assertEquals(2, flights.size());
String departureTimeRequestInput = "2016-05-16T21:00:00.000Z";
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
Date departureDate = sdf.parse(departureTimeRequestInput);
Timestamp departureTimestamp = new Timestamp(departureDate.getTime());
flights = (List<Flight>) entityManager.createQuery(
"SELECT f FROM Flight f "
+ "WHERE "
+ "f.destinationId = :destinationId "
+ "and "
+ "f.arrivalId = :arrivalId "
+ "and "
+ "f.departureTime <= :departureDate "
+ "and "
+ "f.numberOfPassengers <= :numberOfPassengers")
.setParameter("destinationId", 1L)
.setParameter("arrivalId", 3L)
.setParameter("departureDate", departureTimestamp)
.setParameter("numberOfPassengers", 400L)
.getResultList();
assertEquals(1, flights.size());
log.debug("**H2**SIZE: " + flights.size());
}
}
TestH2DatabaseConfiguration.java
@Configuration
@EnableJpaRepositories("com.mycompany.h2.jpa")
@EnableTransactionManagement
public class TestH2DatabaseConfiguration {
final static Logger log = LoggerFactory.getLogger(TestH2DatabaseConfiguration.class);
@Bean
@Qualifier("dataSource")
public DataSource h2DataSource() {
return new EmbeddedDatabaseBuilder().setType(EmbeddedDatabaseType.H2).addScript("classpath:flight.sql").build();
}
@Bean
public EntityManagerFactory entityManagerFactory() {
HibernateJpaVendorAdapter jpaVendorAdapter = new HibernateJpaVendorAdapter();
jpaVendorAdapter.setGenerateDdl(true);
LocalContainerEntityManagerFactoryBean factoryBean = new LocalContainerEntityManagerFactoryBean();
factoryBean.setDataSource(h2DataSource());
factoryBean.setJpaVendorAdapter(jpaVendorAdapter);
factoryBean.setPackagesToScan("com.mycompany.h2.jpa");
factoryBean.setPersistenceUnitName("flight_table");
Properties ps = new Properties();
ps.put("hibernate.dialect", "org.hibernate.dialect.H2Dialect");
ps.put("hibernate.show_sql", "true");
ps.put("hibernate.hbm2ddl.auto", "none");
factoryBean.setJpaProperties(ps);
factoryBean.afterPropertiesSet();
return factoryBean.getObject();
}
@Bean
public PlatformTransactionManager transactionManager() {
JpaTransactionManager txManager = new JpaTransactionManager();
txManager.setEntityManagerFactory(entityManagerFactory());
return txManager;
}
}
飞行.java
public class Flight implements Serializable {
private static final long serialVersionUID = 2608721697556397731L;
@Id
private Long destinationId;
private Long arrivalId;
private Timestamp departureTime;
private Timestamp arrivalTime;
private Long numberOfPassengers;
...
}
飞行.sql
CREATE TABLE flight (
destinationId INTEGER PRIMARY KEY,
arrivalId INTEGER,
departureTime TIMESTAMP,
arrivalTime TIMESTAMP,
numberOfPassengers INTEGER
);
INSERT INTO flight VALUES (1, 3, '2016-05-16 17:30:00.0', '2016-05-18 17:30:00.0', 400);
INSERT INTO flight VALUES (2, 2, '2016-05-17 17:30:00.0', '2016-05-19 17:30:00.0', 200);
关键点:这里的关键点是将用户输入时间传递到 java.sql.Timestamp 对象中,如 FlightTest.java 所示,例如
String departureTimeRequestInput = "2016-05-16T21:00:00.000Z";
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
Date departureDate = sdf.parse(departureTimeRequestInput);
Timestamp departureTimestamp = new Timestamp(departureDate.getTime());
和
...
.setParameter("departureDate", departureTimestamp)
...
更新 2:在下面的事务中插入飞行对象示例
EntityManager entityManager = null;
try {
entityManager = entityManagerFactory.createEntityManager();
EntityTransaction transaction = entityManager.getTransaction();
transaction.begin();
entityManager.persist(flightObject);
entityManager.flush();
transaction.commit();
return flightObject;
}
finally {
entityManager.close();
}
- 将jsp文件下拉列表中的选定项分配给一个java变量(比如String selection)
- 如何在MongoDB中将String转换为Array
- how to split a string with ','
- Protractor:element.getText()返回一个对象,而不是String
- 如何在不在本地下载的情况下将url中提供的文件(pdf/doc)转换为json/string/base64格式
- Javascript 如何强制 string.replace 不将我的字符串解释为正则表达式
- JavaScript警报适用于int,但不适用于string
- javascript/angularjs 将 String 与 number for loop 连接起来
- 如何在Android中将Javascript返回值转换为String
- 如何在javascript中对以下字符串使用string.split()
- 如何在javascript中使用string.replace.将匹配字符串开头的两个不同表达式替换为null
- 使用JavaScript在Json中提取时,将数组的元素转换为String
- 是否存在将String转换为可执行的c++表达式的方法
- JavaScript - String.newProperty vs. String.prototype.newProp
- 如何将参数应用于String.prototype.format函数
- 在JavaFX的String中包含本地javascript源
- 从Java Applet调用方法,Javascript返回[Ljava.lang.String;@7ac79dfa
- Rhino conversion java.lang.String to JavaScript String
- ibmmobilefirst-Class Cast:java.lang.String不能转换为org.mozilla.j
- Spring Data JPA 接收参数值 [2] 与预期类型 [java.lang.String (n/a)] 不匹配