从反应控制台我收到错误消息“无法加载资源:服务器响应状态为 500 ()”,指向 url“:8080/api/review-add”
从 Spring Boot 后端,我收到错误消息“not-null 属性引用 null 或瞬态值:com.reactspringboot.bookclubbackend.entity.Review.account”
问题是在邮递员中执行 POST 请求时,我没有收到错误,并且对象已发布到数据库中。
这是来自 Spring Boot 后端的文件:
论坛.java
@Entity @Table(name="Forum") public class Forum { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name="id") private long id; @Column(name="book_name") private String bookName; @Column(name="book_image") private String bookImage; @Lob @Column(name="description") private String description; @OneToMany(mappedBy = "forum", cascade = CascadeType.ALL) private List<Review> reviews; public Forum() { } public Forum(String bookName, String bookImage, String description, List<Review> reviews) { this.bookName = bookName; this.bookImage = bookImage; this.description = description; this.reviews = reviews; } public long getId() { return id; } public String getBookName() { return bookName; } public void setBookName(String bookName) { this.bookName = bookName; } public String getBookImage() { return bookImage; } public void setBookImage(String bookImage) { this.bookImage = bookImage; } public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } // using 'JsonProperty' to prevent infinite recursion @JsonProperty(access = JsonProperty.Access.WRITE_ONLY) public List<Review> getReviews() { return reviews; } public void setReviews(List<Review> reviews) { this.reviews = reviews; } }
帐户.java
@Entity @Table(name="account") public class Account { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name="id") private long id; @Column(name="account_name") private String accountName; @Column(name="password") private String password; @Column(name="email") private String email; @Column(name="profile_image") private String profileImage; @Column(name="role") private String role; @Column(name="date_joined") @CreationTimestamp private Date dateJoined; @OneToMany(mappedBy = "account", cascade = CascadeType.ALL) private List<Review> reviews; public Account() { } public Account(String accountName, String password, String email, String profileImage, String role, Date dateJoined, List<Review> reviews) { this.accountName = accountName; this.password = password; this.email = email; this.profileImage = profileImage; this.role = role; this.dateJoined = dateJoined; this.reviews = reviews; } public long getId() { return id; } public String getAccountName() { return accountName; } public void setAccountName(String accountName) { this.accountName = accountName; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public String getProfileImage() { return profileImage; } public void setProfileImage(String profileImage) { this.profileImage = profileImage; } public String getRole() { return role; } public void setRole(String role) { this.role = role; } public Date getDateJoined() { return dateJoined; } public void setDateJoined(Date dateJoined) { this.dateJoined = dateJoined; } // using 'JsonProperty' to prevent infinite recursion @JsonProperty(access = JsonProperty.Access.WRITE_ONLY) public List<Review> getReviews() { return reviews; } public void setReviews(List<Review> reviews) { this.reviews = reviews; } }
Review.java
@Entity @Table(name="review") public class Review { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name="id") private long id; @Column(name="date_posted") @CreationTimestamp private Date datePosted; @Lob @Column(name="comment") private String comment; @Column(name="star_rating") private double starRating; //@JsonIgnore @ManyToOne @JoinColumn(name = "account_id",nullable = false, insertable = true, updatable = true) private Account account; //@JsonIgnore @ManyToOne @JoinColumn(name = "forum_id",nullable = false, insertable = true, updatable = true) private Forum forum; public Review() { } public Review(Date datePosted, String comment, double starRating, Account account, Forum forum) { this.datePosted = datePosted; this.comment = comment; this.starRating = starRating; this.account = account; this.forum = forum; } public long getId() { return id; } public Date getDatePosted() { return datePosted; } public void setDatePosted(Date datePosted) { this.datePosted = datePosted; } public String getComment() { return comment; } public void setComment(String comment) { this.comment = comment; } public double getStarRating() { return starRating; } public void setStarRating(double starRating) { this.starRating = starRating; } public Account getAccount() { return account; } public void setAccount(Account account) { this.account = account; } public Forum getForum() { return forum; } public void setForum(Forum forum) { this.forum = forum; } }
ReviewRepository.java
@CrossOrigin(origins = "http://localhost:3000") public interface ReviewRepository extends JpaRepository<Review, Long> { @Query(value = "SELECT * FROM Review r where r.forum_id = :forum_id", nativeQuery = true) public List<Review> getReviewsUsingForumId(@Param("forum_id") Long forum_id); }
ReviewController.java
@CrossOrigin(origins = "http://localhost:3000") @RestController @RequestMapping("/api/") public class ReviewController { @Autowired private ReviewRepository reviewRepository; // create review rest api //@CrossOrigin(origins = "http://localhost:3000") @PostMapping("/review-add") public Review createReview(@RequestBody Review review) { return reviewRepository.save(review); } @GetMapping("/forum-reviews/{forumId}") public List<Review> getReviewsByForumId(@RequestBody @PathVariable Long forumId) { return reviewRepository.getReviewsUsingForumId(forumId); } }
来自 React 前端
PostComponent.js
function PostComponent() { // right now only using static data for testing const [review, setReview] = useState({datePosted: "2023-07-26", comment: "", starRating: 5.0, account: { id: 1 }, forum: { id: 1 }}); const postURL = "http://localhost:8080/api/review-add"; function changeHandler (event) { setReview({comment: event.target.value}); } function submit(event) { event.preventDefault(); axios.post(postURL, review) } useEffect(() => { console.log(review.comment) }, [review]); return ( <div> <div className="container"> <h2>Post Review</h2> <form onSubmit={(event) => submit(event)}> <div className="form-group"> <label>Comment</label> <input placeholder="Commet here" name="comment" className="form=control" value={review.comment} onChange={changeHandler}/> </div> <button>Submit</button> </form> </div> </div> ) } export default PostComponent;
在邮递员正文中,我选择 raw 并设置为 JSON,当我对“审阅”实体使用此 POST 请求时,它会起作用:
{ "datePosted": "2023-07-26", "comment": "From postman.", "starRating": 5.0, "account": { "id": 1 }, "forum": { "id": 1 } }
数据库中存在id为1的论坛和id为1的帐户。
如果有人可以帮助我或指出我解决这个问题,我将不胜感激。我已经被这个问题困扰好几天了,而且我已经没有想法了。
P粉2540777472024-04-06 00:44:01
如果服务器期望接收整个负载:
{ "datePosted": "2023-07-26", "comment": "From postman.", "starRating": 5.0, "account": { "id": 1 }, "forum": { "id": 1 } }
在你执行以下操作后,服务器将不会收到:
setReview({comment: event.target.value});
服务器只会收到:
{ "comment": "From postman." }
当你只想更新状态中的一个属性时,更新仍然需要包含对象的其余部分以保留整个对象:
setReview({...review, comment: event.target.value});
或者:
setReview(r => ({...r, comment: event.target.value}));
顺便说一下...你的浏览器调试工具可以帮助你缩小到这个确切的问题。你可以观察发送的AJAX请求中的负载,看到它不是你期望的内容,并立即排除所有服务器端代码作为问题的原因,开始专注于客户端调试。