Spring: one JPA model, many JSON representations

I am writing a RESTful web service using Spring / JPA. There is a JPA model that opens through a web service. The Course model is quite spacious - in fact, it consists of several data sets: general information, pricing details, and some caches.

The problem I am facing is the inability to release various JSON representations using the same JPA model.

In the first case, I need to return general_infoa dataset for courses:

GET /api/courses/general_info

in the second case, I would like to return only a data set pricing:

GET /api/courses/pricing

I see the following ways to solve this, and not in a specific order:

  • To create models CourseGeneralInfoand CoursePricingJPAs using the source database table as the source. CourseGeneralInfothe model will have its own set of fields, and CoursePricingwill have its own. So I need JSON.

  • To reorganize material from the model / course table so that GeneralInfo and PricingDetails are separate JPA entities. Well, that sounds like the best (imo), although the database is out of date, and this is not something that I can easily change ...

  • Use some kind of DTO and Spring Mappers to transform the JPA model into the view you need in any particular case.

Which approach would you recommend?

+1
source share
2 answers

Spring Data REST 2.1 - Projections ( spring -data-commons).

, :

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

  GeneralInfo getInfo();

}

Spring , , :

GET /api/courses?projection=general_info

https://spring.io/blog/2014/05/21/what-s-new-in-spring-data-dijkstra

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

+1

Spring 4.1, .

from: 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);
    }
}

, , getAllMessages(), @JsonView(View.Summary.class):

[ {
  "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 View , , .

getMessage() ( JSON View), :

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

@JsonView , JSON View ( JSON View, ). , , @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();
    }
}
+2

All Articles