2015-02-11 79 views
1

我正在使用Spring/JPA編寫一個RESTful Web服務。有一個通過Web服務公開的JPA模型。 「課程」模式非常寬敞 - 它實際上由幾組數據組成:一般信息,定價細節和一些緩存。Spring:一個JPA模型,許多JSON respresentations

我遇到的問題是無法使用相同的JPA模型發佈不同的JSON表示。

的在第一種情況下,我只需要返回general_info組數據的課程:

GET /api/courses/general_info

在第二種情況下,我想返回pricing組數據只有:

GET /api/courses/pricing

我看到以下方法來解決這個問題,而不是特別的順序:

  1. 創建CourseGeneralInfoCoursePricing使用 原始數據庫表作爲源的JPA模型。 CourseGeneralInfo模型 將具有其自己的一組字段,並且CoursePricing將具有其自己的字段 。這樣我就可以擁有我需要的JSON。

  2. 將課程模型/表格中的東西重構爲 GeneralInfo和PricingDetails爲單獨的JPA實體。好吧,這聽起來像是最好的一個(IMO)儘管數據庫是遺產,它是不是我可以很容易地改變......

  3. 槓桿某種DTO和Spring Mappers的JPA模型轉換爲任何需要的表示特殊案例。

你會推薦什麼方法?

回答

1

在Spring數據REST 2.1沒有用於此目的的新機制 - 預測(這是現在春天到數據公地的一部分)。

你需要定義接口,正好含有暴露領域:

@Projection(name = "summary", types = Course.class) 
interface CourseGeneralInfo { 

    GeneralInfo getInfo(); 

} 

之後春將能夠自動地發現它在你的源,你可以提出要求,以現有的端點,這樣:基於 https://spring.io/blog/2014/05/21/what-s-new-in-spring-data-dijkstra

春樣本項目具有突出

GET /api/courses?projection=general_info 

https://github.com/spring-projects/spring-data-examples/tree/master/rest/projections

2

我剛剛閱讀了Spring 4.1中的一些非常漂亮的功能,它們允許您通過註釋使用不同的視圖。

來自:https://spring.io/blog/2014/12/02/latest-jackson-integration-improvements-in-spring

public class View { 
    interface Summary {} 
} 

public class User { 

    @JsonView(View.Summary.class) 
    private Long id; 

    @JsonView(View.Summary.class) 
    private String firstname; 

    @JsonView(View.Summary.class) 
    private String lastname; 

    private String email; 
    private String address; 
    private String postalCode; 
    private String city; 
    private String country; 
} 

public class Message { 

    @JsonView(View.Summary.class) 
    private Long id; 

    @JsonView(View.Summary.class) 
    private LocalDate created; 

    @JsonView(View.Summary.class) 
    private String title; 

    @JsonView(View.Summary.class) 
    private User author; 

    private List<User> recipients; 

    private String body; 
} 

由於Spring MVC的@JsonView的支持,就可以選擇,每個處理方法的基礎上,該領域應序列上:

@RestController 
public class MessageController { 

    @Autowired 
    private MessageService messageService; 

    @JsonView(View.Summary.class) 
    @RequestMapping("/") 
    public List<Message> getAllMessages() { 
     return messageService.getAll(); 
    } 

    @RequestMapping("/{id}") 
    public Message getMessage(@PathVariable Long id) { 
     return messageService.get(id); 
    } 
} 

在這個例子中如果檢索到所有消息,則由於使用@JsonView(View.Summary.class)註釋的getAllMessages()方法只有最重要的字段被序列化:

[ { 
    "id" : 1, 
    "created" : "2014-11-14", 
    "title" : "Info", 
    "author" : { 
    "id" : 1, 
    "firstname" : "Brian", 
    "lastname" : "Clozel" 
    } 
}, { 
    "id" : 2, 
    "created" : "2014-11-14", 
    "title" : "Warning", 
    "author" : { 
    "id" : 2, 
    "firstname" : "Stéphane", 
    "lastname" : "Nicoll" 
    } 
}, { 
    "id" : 3, 
    "created" : "2014-11-14", 
    "title" : "Alert", 
    "author" : { 
    "id" : 3, 
    "firstname" : "Rossen", 
    "lastname" : "Stoyanchev" 
    } 
} ] 

在Spring MVC默認配置中,MapperFeature.DEFAULT_VIEW_INCLUSION設置爲false。這意味着,在啓用JSON視圖時,未註釋的字段或屬性(如正文或收件人)不會被序列化。

當特定消息是使用getMessage()處理程序方法檢索(沒有JSON查看指定),所有字段都被序列化爲預期:

{ 
    "id" : 1, 
    "created" : "2014-11-14", 
    "title" : "Info", 
    "body" : "This is an information message", 
    "author" : { 
    "id" : 1, 
    "firstname" : "Brian", 
    "lastname" : "Clozel", 
    "email" : "[email protected]", 
    "address" : "1 Jaures street", 
    "postalCode" : "69003", 
    "city" : "Lyon", 
    "country" : "France" 
    }, 
    "recipients" : [ { 
    "id" : 2, 
    "firstname" : "Stéphane", 
    "lastname" : "Nicoll", 
    "email" : "[email protected]", 
    "address" : "42 Obama street", 
    "postalCode" : "1000", 
    "city" : "Brussel", 
    "country" : "Belgium" 
    }, { 
    "id" : 3, 
    "firstname" : "Rossen", 
    "lastname" : "Stoyanchev", 
    "email" : "[email protected]", 
    "address" : "3 Warren street", 
    "postalCode" : "10011", 
    "city" : "New York", 
    "country" : "USA" 
    } ] 
} 

只有一個類或接口可以與@JsonView註釋被指定,但您可以使用繼承來表示JSON視圖層次結構(如果某個字段是JSON視圖的一部分,則它也將成爲父視圖的一部分)。例如,這種處理方法將序列與@JsonView(View.Summary.class)@JsonView(View.SummaryWithRecipients.class)註釋字段:

public class View { 
    interface Summary {} 
    interface SummaryWithRecipients extends Summary {} 
} 

public class Message { 

    @JsonView(View.Summary.class) 
    private Long id; 

    @JsonView(View.Summary.class) 
    private LocalDate created; 

    @JsonView(View.Summary.class) 
    private String title; 

    @JsonView(View.Summary.class) 
    private User author; 

    @JsonView(View.SummaryWithRecipients.class) 
    private List<User> recipients; 

    private String body; 
} 

@RestController 
public class MessageController { 

    @Autowired 
    private MessageService messageService; 

    @JsonView(View.SummaryWithRecipients.class) 
    @RequestMapping("/with-recipients") 
    public List<Message> getAllMessagesWithRecipients() { 
     return messageService.getAll(); 
    } 
}