使用 Fetch for List进行一对多保存 (POST) 会导致错误请求 (400)
我试图同时保存父实体(一)和子实体(许多)。
我从这里获取帮助< /a> 和 此处。
我有一个如下所示的用户实体:
@Entity
@Table(name = "app_user")
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
public class AppUser {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private Long id;
@Column(name = "salutation")
private String salutation;
@Column(name = "name")
private String name;
@Column(name = "email")
private String email;
@Column(name = "preference")
private String preference;
public AppUser(String salutation, String name, String email, String preference, List<Address> addressList,
List<Expertise> expertise) {
super();
this.salutation = salutation;
this.name = name;
this.email = email;
this.preference = preference;
this.addressList = addressList;
this.expertise = expertise;
}
@OneToMany(orphanRemoval = true, cascade = { CascadeType.PERSIST, CascadeType.MERGE })
@JoinColumn(name = "address_id")
private List<Address> addressList = new ArrayList<>();
@OneToMany(orphanRemoval = true, cascade = { CascadeType.PERSIST, CascadeType.MERGE })
@JoinColumn(name = "expertise_id")
private List<Expertise> expertise = new ArrayList<>();
我的 POST 控制器方法。
@PostMapping("/appUsers")
public ResponseEntity<AppUser> createUser(@RequestBody AppUser appUser) {
try {
AppUser _appUser = appUserRepository.save(
new AppUser(appUser.getSalutation(), appUser.getName(), appUser.getEmail(),
appUser.getPreference(), appUser.getAddressList(),
appUser.getExpertise()));
return new ResponseEntity<>(_appUser, HttpStatus.CREATED);
} catch (Exception e) {
return new ResponseEntity<>(null, HttpStatus.INTERNAL_SERVER_ERROR);
}
}
我的纯 JS(获取)片段:
<script>
async function postDataToServer(postData) {
const baseURL = "http://localhost:8080/api";
try {
const res = await fetch(`${baseURL}/appUsers`, {
method: "post",
headers: {
"Content-Type": "application/json",
Accept: "application/json",
},
body: JSON.stringify(postData),
});
if (!res.ok) {
const message = `An error has occured: ${res.status} - ${res.statusText}`;
throw new Error(message);
}
} catch (err) {
alert(err.message);
}
}
</script>
使用上面的内容,我可以看到表单数据很好地形成,如下所示:
{
"salutation": "Mr.",
"name": "Ajay Kumar",
"email": "[email protected]",
"address_main": "1234 StreetName State 12345",
"address_1": "2345 StreetName State 23456",
"address_2": "3456 StreetName State 34567",
"preference": "Vegeterian",
"expertise": [
"java",
"springboot",
"javascript"
],
"secret": "1abc1234-1abc-4321-1234-1234abcd1234"
}
在提交期间,如果我不选择专业知识,那么一切都会找到。即用户被保存,但如果我选择专业知识复选框,我会在浏览器控制台和 JSON 解析错误控制台收到 400 错误请求消息,如下所示:
2022-02-25 11:02:53.009 WARN 25007 --- [nio-8080-exec-1] .wsmsDefaultHandlerExceptionResolver:已解决[org.springframework.http.converter.HttpMessageNotReadableException:JSON解析错误:无法构造实例
com.spring.boot.rocks.model.Expertise
(尽管至少存在一个 Creator):没有字符串参数构造函数/工厂方法来从字符串值('java')反序列化;嵌套异常是 com.fasterxml.jackson.databind.exc.MismatchedInputException:无法构造 com.spring.boot.rocks.model.Expertise 的实例(尽管至少存在一个 Creator):没有字符串参数从字符串值('java')反序列化的构造函数/工厂方法 [Source: (PushbackInputStream);行:1,列:234](通过参考链:com.spring.boot.rocks.model.AppUser["expertise"]->java.util.ArrayList[0])]
我创建了一个 github 项目。
问题:我缺少什么?如何仅使用纯 JS 将 expertise
集合转换为 List?或者如何处理控制器中的专业知识
集合?
I am trying to save Parent (One) and Children (Many) entities at the same time.
I took help from here and here.
I have an User Entity like below:
@Entity
@Table(name = "app_user")
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
public class AppUser {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private Long id;
@Column(name = "salutation")
private String salutation;
@Column(name = "name")
private String name;
@Column(name = "email")
private String email;
@Column(name = "preference")
private String preference;
public AppUser(String salutation, String name, String email, String preference, List<Address> addressList,
List<Expertise> expertise) {
super();
this.salutation = salutation;
this.name = name;
this.email = email;
this.preference = preference;
this.addressList = addressList;
this.expertise = expertise;
}
@OneToMany(orphanRemoval = true, cascade = { CascadeType.PERSIST, CascadeType.MERGE })
@JoinColumn(name = "address_id")
private List<Address> addressList = new ArrayList<>();
@OneToMany(orphanRemoval = true, cascade = { CascadeType.PERSIST, CascadeType.MERGE })
@JoinColumn(name = "expertise_id")
private List<Expertise> expertise = new ArrayList<>();
My POST controller method.
@PostMapping("/appUsers")
public ResponseEntity<AppUser> createUser(@RequestBody AppUser appUser) {
try {
AppUser _appUser = appUserRepository.save(
new AppUser(appUser.getSalutation(), appUser.getName(), appUser.getEmail(),
appUser.getPreference(), appUser.getAddressList(),
appUser.getExpertise()));
return new ResponseEntity<>(_appUser, HttpStatus.CREATED);
} catch (Exception e) {
return new ResponseEntity<>(null, HttpStatus.INTERNAL_SERVER_ERROR);
}
}
My pure JS (Fetch) snippet:
<script>
async function postDataToServer(postData) {
const baseURL = "http://localhost:8080/api";
try {
const res = await fetch(`${baseURL}/appUsers`, {
method: "post",
headers: {
"Content-Type": "application/json",
Accept: "application/json",
},
body: JSON.stringify(postData),
});
if (!res.ok) {
const message = `An error has occured: ${res.status} - ${res.statusText}`;
throw new Error(message);
}
} catch (err) {
alert(err.message);
}
}
</script>
Using above, I can see the form data nicely forming up like below:
{
"salutation": "Mr.",
"name": "Ajay Kumar",
"email": "[email protected]",
"address_main": "1234 StreetName State 12345",
"address_1": "2345 StreetName State 23456",
"address_2": "3456 StreetName State 34567",
"preference": "Vegeterian",
"expertise": [
"java",
"springboot",
"javascript"
],
"secret": "1abc1234-1abc-4321-1234-1234abcd1234"
}
During submit if I don't select expertise, it all works find. i.e. the user gets saved but if I select expertise checkboxes I get a 400 bad request message at the browser console and JSON parse erroSTS console like this:
2022-02-25 11:02:53.009 WARN 25007 --- [nio-8080-exec-1] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Cannot construct instance of
com.spring.boot.rocks.model.Expertise
(although at least one Creator exists): no String-argument constructor/factory method to deserialize from String value ('java'); nested exception is com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot construct instance ofcom.spring.boot.rocks.model.Expertise
(although at least one Creator exists): no String-argument constructor/factory method to deserialize from String value ('java') at [Source: (PushbackInputStream); line: 1, column: 234] (through reference chain: com.spring.boot.rocks.model.AppUser["expertise"]->java.util.ArrayList[0])]
I created a github project here if any more details are required.
Question: What I am missing? How do I convert expertise
collection to List using pure JS only ? Or how do I handle expertise
collection in controller?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您的表单数据格式不正确。这应该是这样的:
父类中的专业知识和地址是列表,而不是普通的 objectType 实体。如果这两个列表中的任何一个不存在,请在保存之前尝试将它们设置为空列表。
Your form data is not in correct format. This should be like this:
Expertise and address in your parent class are lists, not normal objectType entity. If any of these two lists are not present, try to set them as emptyList before saving.