java – 混合Spring MVC Spring資料休息導致奇怪的MVC響應
我有兩個JPA實體,一個具有SDR匯出的儲存庫,另一個具有Spring MVC控制器和一個未匯出的儲存庫.
MVC暴露實體引用了SDR管理實體.參見下面的程式碼參考.
從UserController檢索使用者時,問題出現. SDR管理實體不會序列化,似乎Spring可能正在嘗試在響應中使用HATEOAS參考.
以下是完全填充使用者的GET如下所示:
{ "username": "[email protected]", "enabled": true, "roles": [ { "role": "ROLE_USER", "content": [], "links": [] // why the content and links? } // no places? ] }
如何使用嵌入式SDR管理實體清楚地從Controller中返回User實體?
實體
@Entity @Table(name = "users") public class User implements Serializable { // UID @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @JsonIgnore private Long id; @Column(unique = true) @NotNull private String username; @Column(name = "password_hash") @JsonIgnore @NotNull private String passwordHash; @NotNull private Boolean enabled; // No Repository @OneToMany(mappedBy = "user", cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER) @NotEmpty private Set<UserRole> roles = new HashSet<>(); // The SDR Managed Entity @ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER) @JoinTable(name = "user_place", joinColumns = { @JoinColumn(name = "users_id") }, inverseJoinColumns = { @JoinColumn(name = "place_id")}) private Set<Place> places = new HashSet<>(); // getters and setters }
回購
@RepositoryRestResource(exported = false) public interface UserRepository extends PagingAndSortingRepository<User, Long> { // Query Methods }
調節器
@RestController public class UserController { // backed by UserRepository private final UserService userService; @Autowired public UserController(UserService userService) { this.userService = userService; } @RequestMapping(path = "/users/{username}", method = RequestMethod.GET) public User getUser(@PathVariable String username) { return userService.getByUsername(username); } @RequestMapping(path = "/users", method = RequestMethod.POST) public User createUser(@Valid @RequestBody UserCreateView user) { return userService.create(user); } // Other MVC Methods }
SDR管理
實體
@Entity public class Place implements Serializable { // UID @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private long id; @NotBlank private String name; @Column(unique = true) private String handle; @OneToOne(cascade = CascadeType.ALL, orphanRemoval = true) @JoinColumn(name = "address_id") private Address address; @OneToOne(cascade = CascadeType.ALL, orphanRemoval = true) @JoinColumn(name = "contact_info_id") private ContactInfo contactInfo; // getters and setters }
回購
public interface PlaceRepository extends PagingAndSortingRepository<Place, Long> { // Query Methods }
簡而言之:Spring Data REST和Spring HATEOAS劫持ObjectMapper,並希望將資源之間的關係用作連結,而不是嵌入資源.
拿一個與另一個實體有一一對應關係的實體:
@Entity public class Person { private String firstName; private String lastName; @OneToOne private Address address; }
SDR / HATEOAS將返回地址作為連結:
{ "firstName": "Joe", "lastName": "Smith", "_links": { "self": { "href": "http://localhost:8080/persons/123123123" }, "address": { "href": "http://localhost:8080/addresses/9127391273" } } }
預設格式可以根據您在類路徑上的具體情況而有所不同.我相信這是我的例子中的HAL,這是你包括SDR和HATEOAS的預設值.根據所述配置可能不同但相似.
當地址由SDR管理時,Spring將會執行此操作.如果它不是由SDR管理的,那麼它將包含響應中的整個地址物件.我懷疑單獨解釋你所看到的行為.
角色
您沒有包含關於UserRole的資訊,但是根據您的程式碼,它似乎可能不在使用者管理之外,因此沒有註冊一個Spring資料儲存庫.如果是這種情況,那就是為什麼它被嵌入 – 沒有其他的“連結”的儲存庫.
角色下的內容和連結看起來像Spring試圖將其序列化為一個頁面.一般情況下,內容將會有一系列的資源,連結將會有諸如“self”的連結或其他資源的連結.我不知道是什麼原因造成的.
地點
Place擁有自己的Spring Data儲存庫,因此它將被視為一個被管理實體,並且被連結而不是嵌入.我懷疑你正在尋找的是一個投影.結帳春天ofollow,noindex" target="_blank">documentation on projections .它看起來像這樣:
@Projection(name = "embedPlaces", types = { User.class }) interface EmbedPlaces { String getUsername(); boolean isEnabled(); Set<Place> getPlaces(); }
這應該是序列化使用者名稱,啟用和角色,並省略一切.我沒有親自使用預測,所以我不能保證它的工作效率,但這是文件中的解決方案.
編輯:當我們在此時,請注意,這也適用於建立或更新資源. Spring將資源作為URL.因此,如果我正在建立一個新人,我的身體可能看起來像個人/地址示例:
{ "firstName": "New", "lastName": "Person", "address": "http://localhost:8080/addresses/1290312039123" }
很容易忘記這些東西,因為廣泛,廣泛,廣泛,廣泛,絕大多數的“REST”API不是REST,SDR / HATEOAS採取REST的觀點(例如,應該是REST).
http://stackoverflow.com/questions/37232377/mixing-spring-mvc-spring-data-rest-results-in-odd-mvc-responses