首頁  >  問答  >  主體

使用Postman時POST請求正常運作,但使用React axios和Spring Boot後端時不起作用

從反應控制台我收到錯誤訊息“無法載入資源:伺服器回應狀態為 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粉208469050P粉208469050218 天前477

全部回覆(1)我來回復

  • P粉254077747

    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請求中的負載,看到它不是你期望的內容,並立即排除所有伺服器端程式碼作為問題的原因,開始專注於客戶端調試。

    回覆
    0
  • 取消回覆