Von der Reaktionskonsole erhalte ich die Fehlermeldung „Ressource konnte nicht geladen werden: Der Server hat mit Status 500 () geantwortet“, die auf die URL „:8080/api/review-add“ verweist
Vom Spring Boot-Backend erhalte ich die Fehlermeldung „not-null property references null or transient value: com.reactspringboot.bookclubbackend.entity.Review.account“
Das Problem besteht darin, dass ich beim Ausführen einer POST-Anfrage in Postman keine Fehlermeldung erhalte und das Objekt in der Datenbank gepostet wird.
Dies ist die Datei aus dem Spring Boot-Backend:
forum.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; } }
account.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); } }
Vom React-Frontend
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;
Im Postman-Body wähle ich Raw aus und stelle JSON ein. Wenn ich diese POST-Anfrage an die Entität „review“ verwende, funktioniert es:
{ "datePosted": "2023-07-26", "comment": "From postman.", "starRating": 5.0, "account": { "id": 1 }, "forum": { "id": 1 } }
Das Forum mit der ID 1 und das Konto mit der ID 1 sind in der Datenbank vorhanden.
Wenn mir jemand helfen oder eine Lösung für dieses Problem finden kann, wäre ich sehr dankbar. Ich stecke schon seit Tagen mit diesem Problem fest und mir gehen die Ideen aus.
如果服务器期望接收整个负载:
在你执行以下操作后,服务器将不会收到:
服务器只会收到:
当你只想更新状态中的一个属性时,更新仍然需要包含对象的其余部分以保留整个对象:
或者:
顺便说一下...你的浏览器调试工具可以帮助你缩小到这个确切的问题。你可以观察发送的AJAX请求中的负载,看到它不是你期望的内容,并立即排除所有服务器端代码作为问题的原因,开始专注于客户端调试。