我正在尝试从数据库表中删除分数,但数据库未更新

问题描述 投票:0回答:1

我正在编写一个java spring boot后端,其方法是submitAnswers,它接受一个键值对的JSON数组,这些键值对代表个性测验的问题和答案键,并为登录后端的当前用户分配完整的个性分数。我编写了我的方法,以便如果当前用户有与其 id 关联的分数,那么我会删除表中现有的分数对象(具有当前用户 id)。但由于某种原因,如果当前登录的用户有一个与之关联的分数对象,我的代码不会删除该分数条目。当我将问答 JSON 数组提交到提交答案端点时,在我的 IntelliJ IDE 中收到错误: java.sql.SQLIntegrityConstraintViolationException:键“score.user_entity_id”的重复条目“153”,其中 153 是当前用户。

这是我的 SubmitAnswers 方法的代码


package com.wang.app.rest.Controller;


import com.wang.app.rest.Models.*;
import com.wang.app.rest.Repo.ScoreRepository;
import com.wang.app.rest.Repo.UserRepository;
import jakarta.annotation.PostConstruct;
import jakarta.transaction.Transactional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import com.wang.app.rest.service.ScoreCalculationService;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@RestController
public class QuizController {

    @Autowired
    private UserRepository userRepository;

    @Autowired
    private ScoreRepository scoreRepository;

    @Autowired
    private ScoreCalculationService scoreCalculationService; //inject the service into the controller

    private Map<Integer, AnswerInfo> questionToMap = new HashMap<>();
    //we use map interface type to make code more flexible...general map type
    //if we wanna change to a different type of map, we can do that easily
    //just change the right side of the assignment operator to a different type of map

    //(1) Extraversion, (2) Agreeableness, (3) Conscientiousness, (4) Emotional Stability, or (5) Intellect/Imagination)
    // and its direction of scoring (+ or -). These numbers should not be included in the actual survey questionnaire. For further information on scoring IPIP scales, click the following link:

    //keys in the hash map are the question numbers, values are the answer info objects
    @PostConstruct
    //this postConstruct ensures questionToMap is initialized as soon as controller is created, before requests made
    public void initQuestionToMap() {
        questionToMap.put(1, new AnswerInfo(1, "+"));
        questionToMap.put(2, new AnswerInfo(2, "-"));
        questionToMap.put(3, new AnswerInfo(3, "+"));
        questionToMap.put(4, new AnswerInfo(4, "-"));
        questionToMap.put(5, new AnswerInfo(5, "+"));
        questionToMap.put(6, new AnswerInfo(1, "-"));
        questionToMap.put(7, new AnswerInfo(2, "+"));
        questionToMap.put(8, new AnswerInfo(3, "-"));
        questionToMap.put(9, new AnswerInfo(4, "+"));
        questionToMap.put(10, new AnswerInfo(5, "-"));
        questionToMap.put(11, new AnswerInfo(1, "+"));
        questionToMap.put(12, new AnswerInfo(2, "-"));
        questionToMap.put(13, new AnswerInfo(3, "+"));
        questionToMap.put(14, new AnswerInfo(4, "-"));
        questionToMap.put(15, new AnswerInfo(5, "+"));
        questionToMap.put(16, new AnswerInfo(1, "-"));
        questionToMap.put(17, new AnswerInfo(2, "+"));
        questionToMap.put(18, new AnswerInfo(3, "-"));
        questionToMap.put(19, new AnswerInfo(4, "+"));
        questionToMap.put(20, new AnswerInfo(5, "-"));
        questionToMap.put(21, new AnswerInfo(1, "+"));
        questionToMap.put(22, new AnswerInfo(2, "-"));
        questionToMap.put(23, new AnswerInfo(3, "+"));
        questionToMap.put(24, new AnswerInfo(4, "-"));
        questionToMap.put(25, new AnswerInfo(5, "+"));
        questionToMap.put(26, new AnswerInfo(1, "-"));
        questionToMap.put(27, new AnswerInfo(2, "+"));
        questionToMap.put(28, new AnswerInfo(3, "-"));
        questionToMap.put(29, new AnswerInfo(4, "+"));
        questionToMap.put(30, new AnswerInfo(5, "-"));
        questionToMap.put(31, new AnswerInfo(1, "+"));
        questionToMap.put(32, new AnswerInfo(2, "-"));
        questionToMap.put(33, new AnswerInfo(3, "+"));
        questionToMap.put(34, new AnswerInfo(4, "-"));
        questionToMap.put(35, new AnswerInfo(5, "+"));
        questionToMap.put(36, new AnswerInfo(1, "-"));
        questionToMap.put(37, new AnswerInfo(2, "+"));
        questionToMap.put(38, new AnswerInfo(3, "-"));
        questionToMap.put(39, new AnswerInfo(4, "+"));
        questionToMap.put(40, new AnswerInfo(5, "-"));
        questionToMap.put(41, new AnswerInfo(1, "+"));
        questionToMap.put(42, new AnswerInfo(2, "-"));
        questionToMap.put(43, new AnswerInfo(3, "+"));
        questionToMap.put(44, new AnswerInfo(4, "-"));
        questionToMap.put(45, new AnswerInfo(5, "+"));
        questionToMap.put(46, new AnswerInfo(1, "-"));
        questionToMap.put(47, new AnswerInfo(2, "+"));
        questionToMap.put(48, new AnswerInfo(3, "-"));
        questionToMap.put(49, new AnswerInfo(4, "+"));
        questionToMap.put(50, new AnswerInfo(5, "-"));
    }
    //WHY IS THE return type map and not Hashmap



    @PostMapping("/submit-answers")
    @Transactional
    public ResponseEntity<Score> submitAnswers(@RequestBody Map<Integer, Integer> answersData, @AuthenticationPrincipal CustomUserDetails customUserDetails) {
        UserEntity currentUserEntity = customUserDetails.getUserEntity();

        // If currentUserEntity is a new entity (not yet saved), save it first so it has an ID
        if (currentUserEntity.getId() == null) {
            userRepository.save(currentUserEntity);
        } else if (currentUserEntity.getScore() != null) {
//            Score oldScore = currentUserEntity.getScore();// Unlink from the score
//            currentUserEntity.setScore(null); // Save the user entity without the score///should delete it all
//            scoreRepository.delete(oldScore); // Delete old score from database
            Score scoreRemove = scoreRepository.findById(currentUserEntity.getScore().getId()).get();
            scoreRepository.delete(scoreRemove);
        }


        // Creating answer objects and associating them with the user
        List<Answer> answers = new ArrayList<>();
        for (Map.Entry<Integer, Integer> entry : answersData.entrySet()) {
            Integer questionId = entry.getKey();
            Integer answerValue = entry.getValue();

            Answer answer = new Answer(questionId, answerValue);
            answer.setUserEntity(currentUserEntity); // Associate the answer with the user
            answers.add(answer);  // Add the answer to the answers list
        }

        // Set answers for the user
        currentUserEntity.setAnswers(answers);

        // Calculating score based on answers
        Score score = (scoreCalculationService.calculateScore(answers, questionToMap));//buggy still if i do score.setUsereNTTIY...
//        score.setUserEntity(currentUserEntity);//the culprit here...
        score.setUserEntity(currentUserEntity); // Set the relationship in the Score entity first
        currentUserEntity.setScore(score);
        currentUserEntity.setUsername(customUserDetails.getUsername());
        // Associate the score with the user on both sides of the relationship
//if setting relationship in userentity first, then set into score....relationship might point to entity that hasnt been persistee dyet

        // Save the user entity which should cascade the saves to Score and Answer
        userRepository.save(currentUserEntity);

        return ResponseEntity.ok(score);
   }
}

这是我的 Score 和 UserEntity 模型:

package com.wang.app.rest.Models;

import jakarta.persistence.*;

@Entity

public class Score {


    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;


    @OneToOne(fetch = FetchType.EAGER)
    @JoinColumn(name = "user_entity_id")
    private UserEntity user;
    //this is a foreign key
    //should store the same value of userentity's id.

    @Column
    private int Extraversion;

    @Column
    private int Agreeableness;

    private int Conscientiousness;

    private int EmotionalStability;

    private int Intellect;

    public void setId(Long id) {
        this.id = id;
    }

    public Long getId() {
        return id;
    }

    public int getExtraversion() {
        return Extraversion;
    }

    public void setExtraversion(int extraversion) {
        Extraversion = extraversion;
    }

    public int getAgreeableness() {
        return Agreeableness;
    }

    public void setAgreeableness(int agreeableness) {
        Agreeableness = agreeableness;
    }

    public int getConscientiousness() {
        return Conscientiousness;
    }

    public void setConscientiousness(int conscientiousness) {
        Conscientiousness = conscientiousness;
    }

    public int getEmotionalStability() {
        return EmotionalStability;
    }

    public void setEmotionalStability(int emotionalStability) {
        EmotionalStability = emotionalStability;
    }
    public int getIntellect() {
        return Intellect;
    }

    public void setIntellect(int intellect) {
        Intellect = intellect;
    }


    public UserEntity getUserEntity() {
        return user;
    }

    @Override
    public String toString() {
        return "Score{" +
                "extraversion=" + getExtraversion() +
                ", agreeableness=" + getAgreeableness() +
                ", conscientiousness=" + getConscientiousness() +
                ", emotionalStability=" + getEmotionalStability()+
                ", intellect=" +getIntellect() +
                '}';
    }
    public void setUserEntity(UserEntity user) {
        this.user = user;
    }

}
package com.wang.app.rest.Models;

import jakarta.persistence.*;
import jdk.jfr.DataAmount;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.security.core.userdetails.UserDetails;

import java.util.ArrayList;
import java.util.List;


@Table(name = "users")
@Data
@NoArgsConstructor
@Entity
public class UserEntity {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @OneToOne
    @JoinColumn(name="id")
    @MapsId
    private User user;

    private String username;

    private String password = "defaultPassword";


    @ManyToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL) //want roles to be shown
    //fetchtype eager: when we get user, we want to get roles as well
    //cascade type all: if we delete user, we want to delete roles as well
    @JoinTable(name = "user_roles", joinColumns = @JoinColumn(name = "user_id", referencedColumnName = "id"),
            inverseJoinColumns = @JoinColumn(name = "role_id", referencedColumnName = "id"))
    private List<Role> roles = new ArrayList<>();

    @OneToMany(mappedBy = "user", cascade = CascadeType.ALL)
    private List<Answer> answers;

    @OneToOne(mappedBy = "user", fetch = FetchType.LAZY, cascade = CascadeType.ALL, orphanRemoval = true)
    //added cascadetype.all based on baeldung
    private Score score;

    public void setScore(Score score){
        this.score = score;
    }



}

我遵循了本教程:

//https://www.geeksforgeeks.org/spring-data-jpa-delete-records-from-mysql/
    

从我的分数表中删除分数记录..

spring-boot jpa liquibase
1个回答
0
投票

您向 UserEntity 添加了 mappedBy 属性,这意味着现在它负责管理关系。

您可以通过将 UserEntity 的分数设置为 null 来删除分数。

currentUserEntity.setScore(null);
© www.soinside.com 2019 - 2024. All rights reserved.