POST请求在Postman中工作,但不适用于使用Sping Boot 后端的React Axios

hrirmatl  于 2023-08-04  发布在  iOS
关注(0)|答案(1)|浏览(94)

从react控制台,我收到错误消息“Failed to load resource:服务器以500()的状态响应”指向url“:8080/API/review-add”
从spring Boot 后端我得到错误消息“not-null property references a null or transient value:com.reactspringboot.bookclubbackend.entity.Review.account”
问题是当在postman中执行POST请求时,我没有得到错误,对象被发送到数据库中。
以下是Sping Boot 后端的文件:
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);
    }
}


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;


在postman body中,我选择raw并设置为JSON,当我使用这个POST请求“Review”实体时,它工作:

{
    "datePosted": "2023-07-26",
    "comment": "From postman.",
    "starRating": 5.0,
    "account": {
        "id": 1
    },
    "forum": {
        "id": 1
    }
}


ID为% 1的论坛和ID为% 1的帐户在数据库中存在。
如果有人能帮助我或指出我解决这个问题,我将不胜感激。我在这个问题上被困了好几天,已经无计可施了。

js4nwp54

js4nwp541#

如果服务器需要整个payload:

{
    "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 请求中发送的有效负载,发现它不是您所期望的,并立即排除所有服务器端代码作为罪魁祸首,并开始专注于客户端调试。

相关问题