【问题标题】:JPA does not save property in MYSQL databaseJPA 不在 MYSQL 数据库中保存属性
【发布时间】:2020-07-30 16:50:42
【问题描述】:

我现在正在学习 Spring Boot,我将它用作后端,并将 React 用作​​前端。

我正在通过 JPA Hibernate 保存数据,每个属性都被正确保存,但是 team_name 没有被保存,我不知道为什么它没有被保存,希望你能帮我解决这个问题。

我的 MySQL 桌面播放器有 4 个属性: id为主键,age,name,team_name为外键

那么 MySQL 表 Team 有一个属性名称,它是主键。并且正如你在 Java 代码中看到的那样,玩家和团队是有关系的。

当我可以记录 this.state.team 属性时,它会为我提供团队名称,它不为空,只是没有保存在 MySQL 表中。

更新代码:

Java 播放器实体:

@Entity
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Player {

    @Id
    private String id;


    private String name;
    private String age;

    @ManyToOne 
    @JsonBackReference
    private Team team;


}

Java 团队实体:

@Entity
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Team {

    @Id
    private String name;

    @JsonManagedReference
    @OneToMany(mappedBy = "team")
    private List<Player> players;

}

反应代码:

class Player extends Component {

    constructor(){
        super();
        this.state={
            player:{},
            playerName: null,
            id:null,
            flag:null,
            age:null,
            team:null,
            name: null
    }
    this.handleSubmit = this.handleSubmit.bind(this);
    this.handleChange = this.handleChange.bind(this);
    this.getPlayerData = this.getPlayerData.bind(this)
    }

    async getPlayerData(playerName){
        const proxyurl = "https://cors-anywhere.herokuapp.com/";    
        const url = "https://www.hltv.org/search?term=" + playerName
        const fullUrl= proxyurl+url
        const response = await fetch(fullUrl)
        const arr = await response.json()
        const player = arr[0].players[0];
        const fullName= player.firstName + " " + player.lastName


         this.setState({
            playerName: player.nickName,
            id: player.id,
            flag: player.flagUrl,
            age:null,
            team:{
                name: player.team.name
            },
            name: fullName

        })
    }

    async createNonExistingTeam(){
        const teamData={
            name:this.state.team.name
        }

         await fetch("/api/team" , {
            method: 'POST' ,
            headers : {
              'Accept' : 'application/json',
              'Content-Type' : 'application/json'
            },
            body: JSON.stringify(teamData)
        })
    }

    async createNonExistingPlayer(){
        const data={
            id: this.state.playerName,
            age: null,
            name:this.state.name,
            team_name: this.state.team.name
        }
        await fetch("/api/player" , {
            method: 'POST' ,
            headers : {
              'Accept' : 'application/json',
              'Content-Type' : 'application/json'
            },
            body: JSON.stringify(data)
        })
        await this.handleSubmit()
    }


    async handleSubmit(event){
        const {playerName} = this.state


            try{
                const response =  await fetch(`/api/player/${playerName}` , {
                    method: 'GET' ,
                    headers : {
                      'Accept' : 'application/json',
                      'Content-Type' : 'application/json'
                    }})
                const output = await response.json();
                this.setState({
                    player:output
                })
            } catch(e){

                await this.getPlayerData(playerName)
                await this.createNonExistingTeam()
                await this.createNonExistingPlayer()

            }

        const style = {
            marginTop: 20,
            marginLeft: 30
        }

        const {player} = this.state
        const {playerData} = this.state
        const {flag} = this.state
        const {id} = this.state



const picLink = "https://static.hltv.org//images/playerprofile/bodyshot/compressed/" + id + ".png"
        const data = 
        <div>
            <PlayerData
                style={style} 
                ign={player.id}
                name={player.name} 
                pic={picLink}
                nation={flag}
                age={player.age}

            />

        </div>



        ReactDOM.render(data,document.getElementById('playerData'))


}





    async handleChange(event) {
        this.setState({
          [event.target.name]: event.target.value
        });
    }

编辑控制器代码:

玩家控制器:

@RestController
@RequestMapping("/api")
public class PlayerController {

    @Autowired
    private PlayerRepository playerRepository;

    @GetMapping("/players")
    List<Player>getAllPlayers(){
        return playerRepository.findAll();
    }

    @PostMapping("/player")
    ResponseEntity<Player> createPlayer(@Valid @RequestBody Player player) throws URISyntaxException{
        Player result = playerRepository.save(player);

        return ResponseEntity.created(new URI("/api/player" + result.getId())).body(player);
    }

    @GetMapping("/player/{id}")
    ResponseEntity<?> getPlayer(@PathVariable String id){
        Optional<Player>result =  playerRepository.findById(id);
        ResponseEntity<Player> resMap = result.map(response->ResponseEntity.ok().body(response)).orElse(new ResponseEntity<>(HttpStatus.NOT_FOUND));
        return resMap;
    }

    @GetMapping("/{name}/players")
    List<Player> findPlayers(@PathVariable Team name){
        return playerRepository.findByTeam(name);
    }
}

团队控制器:

@RestController
@RequestMapping("/api")
public class TeamController {

    @Autowired
    private TeamRepository tRepository;

    @PostMapping("/team")
    ResponseEntity<Team> createTeam(@Valid @RequestBody Team team) throws URISyntaxException{
        Team result = tRepository.save(team);

        return ResponseEntity.created(new URI("/api/team/" + result.getName())).body(team);
    }


    }

编辑:

我意识到,当我在 Java 的 create player 方法中打印我的球员时,球队显示为 NULL,所以我想我的 POST 请求有问题。

【问题讨论】:

  • 请给控制器提供服务层。
  • @Nikolas 这个请求有必要吗?它并没有真正做某事
  • 如果你调试createPlayer控制器方法,你能看到正确的团队价值吗?
  • @Rohit 是的,当我记录它时,我得到了正确的值,但它只是没有保存在数据库中。

标签: mysql reactjs hibernate spring-boot jpa


【解决方案1】:

我解决了我的问题。我发现我的 POST 请求有误。我将我的 getPlayerData 方法更改为:

this.setState({
            playerName: player.nickName,
            id: player.id,
            flag: player.flagUrl,
            age:null,
            team:{
                name: player.team.name
            },
            name: fullName
            })

在我的 POST 请求中,我创建了一个新变量。

const dat={
   name: this.state.team.name
}    

并像这样更改了我的数据对象:

const data={
            id: this.state.playerName,
            age: null,
            name:this.state.name,
            team: dat
        }

【讨论】:

    【解决方案2】:

    您的前端Player 组件不代表PlayerTeam 实体关系。

    应该是:

    {
        playerName: player.nickName,
        id: player.id,
        flag: player.flagUrl,
        age:null,
        team:{
                name:player.team.name
            },
        name: fullName
    }
    

    【讨论】:

    • 可能是因为 name 前面缺少逗号。我现在更正了。在 REST 控制器的 createPlayer 方法中,Player 是否正确填充了 Team
    • 没有语法错误,但我的 MySQL 表中的 team_name 行仍然是空的
    • 从 FE 接收的 JSON 是否正确反序列化为后端的 Player 对象?
    • @PostMapping("/player") ResponseEntity&lt;Player&gt; createPlayer(@Valid @RequestBody Player player) throws URISyntaxException{ //If you log the player here, does it contain the team. Player result = playerRepository.save(player); return ResponseEntity.created(new URI("/api/player" + result.getId())).body(player); }
    • 我不太清楚你的意思,但是当我通过 POST 请求保存我的播放器时,我的 MySQL 表中的属性名称和 ID 已正确填写,但 team_name 保持为空
    【解决方案3】:

    您的映射不正确,您可以删除 @Table 注释,因为这是 多余的。

    您也不应该使用@Data 注解,因为这可能会导致双向引用的 StackOverflowError。

    首先使用@ManyToOne 而不是@OneToOne:

    @Entity
    @Getter @Setter
    @NoArgsConstructor
    @AllArgsConstructor
    public class Player {
    
        @Id
        private String id;
    
        private String name;
        private String age;
    
        @ManyToOne 
        @JsonBackReference
        private Team team;
    }
    

    那么你必须使用 mappedBy 属性告诉 JPA 有一个反向引用:

    @Entity
    @Getter @Setter
    @NoArgsConstructor
    @AllArgsConstructor
    @Table(name="team")
    public class Team {
    
        @Id
        private String name;
    
        @JsonManagedReference
        @OneToMany(mappedBy = "team")
        private List<Player> players;
    }
    

    【讨论】:

    • 但是一个玩家只能拥有一支球队,这样还有可能吗?
    • 我尝试了这些更改,但仍然没有将 team_name 保存在 MySQL 表中
    • 您应该按照其他人的建议显示控制器代码,以查看您如何将请求映射到实体
    猜你喜欢
    • 2015-06-19
    • 2017-06-15
    • 1970-01-01
    • 2016-05-09
    • 1970-01-01
    • 2020-07-15
    • 2014-06-30
    • 1970-01-01
    相关资源
    最近更新 更多