2015-09-21 74 views
1

幾年後,我回到Java嘗試使用Java實現RESTful WS。我發現很多教程和文章使用彈簧和它的彈簧啓動擴展在之上頂部。在設置完所有的第一個問題後,我終於有了一個正在運行的WS,並且可以訪問(例如,使用curl從CLI訪問)。Java spring boot rest服務奮鬥

不幸的是我得到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); 
    } 
} 

如果我所說的WS與CMD curl -g localhost:8080/carts/id/1curl -g localhost:8080/carts/notification/1我得到了第二個味精的異常(對於名稱[cart_id][notification_id])。如果我打電話給cmd curl -g localhost:8080/carts/ean/2550000017884,我得到了第一個msg的異常(對於position [1])。

db表的樣子:

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可能會有所幫助,但因爲所有的彈簧引導教程與JPA庫工作,我也不知道如何從持久調用這些命名查詢。 ..

編輯:加入我的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> 
+2

從查詢方法中刪除'@ Param',這些僅在使用'@ Query'時需要(如參考指南中所述)。另外你的'findByCartId'和默認的'findOne'是一樣的,所以它是非常沒用的imho。 –

+0

@ M.Deinum謝謝,這有助於擺脫*參數名稱*異常味精,現在我只得到**'參數與該位置[1]不存在;'**爲所有三種方法... – shadyyx

+0

我想對於初學者刪除'findByCartId'由33%減少了:)你的問題(這也增加任何在'findOne'方法。你可以添加完整的堆棧跟蹤,也許你的POM(聚甲醛的至少依賴性節) 。 –

回答

2

@Param作品(而不是給了一個錯誤)的事實表明,一個預先定義的查詢被執行。如果沒有查詢,@Param會失敗。

Spring Data使用策略來確定要使用哪個查詢默認執行它使用CREATE_IF_NOT_FOUNDlookup strategy。它首先嚐試查找預定義的查詢,這可以是方法上的@Query或JPA上的@NamedQuery(在後一種情況下,它正在查找名爲查詢的<entity-name>.<method-name>)。如果這些都不適用,它將根據該方法創建一個查詢。

在你的情況下,你有一個名字爲Cart.findByCartId的命名查詢(對於其他方法也是如此)。 Spring Data檢測到這個查詢並執行它。由於您的@Param它試圖找到一個名爲cart_id參數,但該名稱實際上是cartId(見命名查詢)。

解決您的問題,無論是 1.修正了@Param註釋在你的方法,以指向正確的參數名稱 2.拆下@Param@NamedQuery小號 3.開關彈簧數據JPA的CREATE查找策略和刪除@Param

+0

我走了第一個解決方案。這使我可以使用查找策略來創建新的查詢(如果缺失)並使用命名查詢以及我在使用Persistence的時候已經使用的命名查詢。再次感謝你! – shadyyx