【发布时间】:2015-09-21 12:44:35
【问题描述】:
几年后,我回到 Java 尝试使用 Java 实现 RESTful WS。我找到了大量关于使用 Spring 实现它的教程和文章,它是 Maven 之上的 Spring boot 扩展。在设置完所有问题后,我终于有了一个正在运行且可访问的 WS(例如,从 CLI 使用 curl)。
不幸的是,我收到了java.lang.IllegalArgumentException 异常,并带有以下两条消息:
java.lang.IllegalArgumentException: 具有该位置 [1] 的参数不存在
和
java.lang.IllegalArgumentException:名称为 [cart_id] 的参数不存在
这是我缩短的Entity 课程:
@Entity
@Table(name = "cart", catalog = "table1", schema = "")
@XmlRootElement
@NamedQueries({
@NamedQuery(name = "Cart.findAll", query = "SELECT c FROM Cart c"),
@NamedQuery(name = "Cart.findByCartId", query = "SELECT c FROM Cart c WHERE c.cartId = :cartId"),
@NamedQuery(name = "Cart.findByBarcode", query = "SELECT c FROM Cart c WHERE c.barcode = :barcode"),
@NamedQuery(name = "Cart.findByCartTypeId", query = "SELECT c FROM Cart c WHERE c.cartTypeId = :cartTypeId"),
@NamedQuery(name = "Cart.findByCartStyleId", query = "SELECT c FROM Cart c WHERE c.cartStyleId = :cartStyleId"),
@NamedQuery(name = "Cart.findByCartName", query = "SELECT c FROM Cart c WHERE c.cartName = :cartName"),
@NamedQuery(name = "Cart.findByNotificationId", query = "SELECT c FROM Cart c WHERE c.notificationId = :notificationId"),
@NamedQuery(name = "Cart.findByCartContentId", query = "SELECT c FROM Cart c WHERE c.cartContentId = :cartContentId"),
@NamedQuery(name = "Cart.findByStationId", query = "SELECT c FROM Cart c WHERE c.stationId = :stationId"),
@NamedQuery(name = "Cart.findByUserId", query = "SELECT c FROM Cart c WHERE c.userId = :userId"),
@NamedQuery(name = "Cart.findByStatus", query = "SELECT c FROM Cart c WHERE c.status = :status")})
public class Cart implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Basic(optional = false)
@Column(name = "cart_id")
private Long cartId;
@Size(max = 50)
private String barcode;
@Column(name = "notification_id")
private Integer notificationId;
// other properties, getters and setters follow ...
}
这里是存储库:
@RepositoryRestResource
public interface CartDAO extends CrudRepository<Cart, Long> {
/**
* Returns cart by it's ID.
* @param cartId
* @return Cart
*/
public Cart findByCartId(@Param("cart_id") Long cartId);
/**
* Returns cart by it's barcode (EAN).
* @param barcode
* @return Cart
*/
public Cart findByBarcode(String barcode);
/**
* Returns all the carts belonging to notification (by notification ID).
* @param notificationId
* @return List of Carts
*/
public List<Cart> findByNotificationId(@Param("notification_id") Integer notificationId);
}
这是控制器:
@RestController
@RequestMapping("/carts")
public class CartController {
@Autowired
private CartDAO cartDao;
@RequestMapping(value="/id/{cartId}", method = RequestMethod.GET)
public Cart getCartById(@PathVariable Long cartId) {
return cartDao.findByCartId(cartId);
// return cartDao.findOne(cartId);
}
@RequestMapping(value="/ean/{barcode}", method = RequestMethod.GET)
public Cart getCartByBarcode(@PathVariable String barcode) {
return cartDao.findByBarcode(barcode);
}
@RequestMapping(value="/notification/{notificationId}", method = RequestMethod.GET)
public List<Cart> getCartByNotification(@PathVariable Integer notificationId) {
return cartDao.findByNotificationId(notificationId);
}
}
如果我使用 cmd curl -g localhost:8080/carts/id/1 或 curl -g localhost:8080/carts/notification/1 调用 WS,我会收到第二个 msg 的异常(对于名称 [cart_id] 或 [notification_id])。如果我调用 cmd curl -g localhost:8080/carts/ean/2550000017884 我得到了第一个 msg 的异常(对于 position [1])。
数据库表如下所示:
cart
===========================================
cart_id INT (PK, auto_increment)
notification_id INT (FK)
barcode VARCHAR(13) (NOT NULL, UNIQUE)
...
但是,如果我为CartController.getCartById() 中的两行切换注释(即让return cartDao.findOne(cartId); 被调用而不是return cartDao.findByCartId(cartId);),那么我终于可以毫无例外地看到一个有效的响应。
但是我在这里做错了什么?显然我遗漏了一些东西(以及所有的教程)。
PS:我已经使用persistance unit 创建了所有实体 - 我让 PU 连接到我的数据库并为我创建所有实体。过去我喜欢以这种方式工作,因为 PU 可以非常快速地处理两侧的变化并将它们镜像到另一侧。在 PU 的帮助下,我还有很多 @NamedQueries 可能会有所帮助,但由于所有 spring-boot 教程都在使用 JPA 存储库 我不知道如何从 Persistence...
编辑:添加我的 pom.xml 的依赖项部分:
<dependencies>
<!-- Get the dependencies of a web application -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- DB -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-rest</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-commons</artifactId>
<type>jar</type>
</dependency>
</dependencies>
【问题讨论】:
-
从查询方法中删除
@Param,仅当您使用@Query时才需要(如参考指南中所述)。此外,您的findByCartId与默认的findOne相同,因此恕我直言,它毫无用处。 -
@M.Deinum 谢谢,这有助于摆脱 parameter name 异常消息,现在我只得到
Parameter with that position [1] did not exist;三个方法... -
我会首先删除
findByCartId,这可以将您的问题减少 33% :) (它也没有增加findOne方法。你能添加完整的堆栈跟踪,也许你的 pom (至少 pom 的依赖部分)。 -
@M.Deinum 我首先实现了
findByCartId,因为我的@Id是Integer类型。然后我发现有本地存储库的方法findById正在接受Long所以我在我的实体中将它更改为Long来尝试一下......如果我发现findByCartId因为Integer正在工作,我会把我的@Id还给Integer... -
添加了来自
pom.xml的@M.Deinum 依赖项。
标签: java spring spring-boot