gpt4 book ai didi

java - 混合 Spring MVC + Spring Data Rest 导致奇怪的 MVC 响应

转载 作者:太空狗 更新时间:2023-10-29 22:58:34 25 4
gpt4 key购买 nike

我有两个 JPA 实体,一个带有 SDR 导出存储库,另一个带有 Spring MVC Controller 和一个非导出存储库。

MVC 公开的实体引用了 SDR 管理的实体。请参阅下面的代码引用。

UserController 检索 User 时,问题就出现了。 SDR 托管实体不会序列化,似乎 Spring 可能会尝试在响应中使用 HATEOAS 引用。

这是完全填充的 UserGET 的样子:

{
"username": "foo@gmail.com",
"enabled": true,
"roles": [
{
"role": "ROLE_USER",
"content": [],
"links": [] // why the content and links?
}
// no places?
]
}

如何使用嵌入式 SDR 托管实体从我的 Controller 中直接返回 User 实体?

Spring MVC 管理

实体

@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
}

repo

@RepositoryRestResource(exported = false)
public interface UserRepository extends PagingAndSortingRepository<User, Long> {
// Query Methods
}

Controller

@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
}

repo

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 时,这是默认设置。 根据所述配置,它可能不同但相似

Address 由 SDR 管理时,Spring 将执行此操作。如果它根本不由 SDR 管理,它将在响应中包含整个地址对象。我怀疑仅凭这一点就可以解释您所看到的行为。

角色

您没有包含有关 UserRole 的信息,但根据您的代码,它似乎不是在 User 之外管理的,因此没有 Spring Data 存储库挂号的。如果是这种情况,这就是它被嵌入的原因——没有其他存储库可以“链接”到。

roles 下的 contentlinks 看起来像 Spring 试图像 Page 一样序列化它。通常,content 将包含一组资源,links 将包含诸如“self”之类的链接或指向其他资源的链接。我不确定是什么原因造成的。

地点

Place 有自己的 Spring Data 存储库,因此它将被视为托管实体并链接到而不是嵌入。我怀疑你要找的是一个投影。检查 Spring documentation on projections .它看起来像这样:

@Projection(name = "embedPlaces", types = { User.class })
interface EmbedPlaces {
String getUsername();
boolean isEnabled();
Set<Place> getPlaces();
}

应该序列化用户名、启用和角色,并忽略其他所有内容。我还没有亲自使用过投影,所以我不能保证它的效果如何,但这是文档中的解决方案。

编辑:在我们进行时请注意,这也适用于创建或更新资源。 Spring 将资源作为 URL。所以以人/地址为例,如果我要创建一个新人,我的 body 可能看起来像:

{
"firstName": "New",
"lastName": "Person",
"address": "http://localhost:8080/addresses/1290312039123"
}

很容易忘记这些事情,因为绝大多数“REST”API 都不是 REST,SDR/HATEOAS 对 REST 持一种固执己见的观点(例如,它应该是 REST,其中之一).

关于java - 混合 Spring MVC + Spring Data Rest 导致奇怪的 MVC 响应,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37232377/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com