【问题标题】:Foreign Key is only working on some models in Spring JPA project外键仅适用于 Spring JPA 项目中的某些模型
【发布时间】:2020-03-08 20:39:16
【问题描述】:

我的 spring jpa 项目遇到了一个奇怪的问题。基本上对于我的一个模型,外键似乎没有按预期工作。 在我的项目中,我有一个模型类“Player”和另一个“PlayerStats”。

在“玩家统计”中,我为单个玩家添加统计数据并将其存储在我的数据库中。 我使用基本的 html 作为简单的 web 表单进行数据输入。 这工作正常,但列“player_id”始终为 NULL。 它不会打扰我,但我想在另一个表中显示每个玩家的个人统计数据,如果我无法解决这个问题,其他所有玩家的统计数据都可以查看。

然而,我在我的项目中为不同的模型类设置了相同的方式,我没有问题。例如,我有一个用户模型类,其中“user_id”用作模型类“团队”和“玩家”中的外键。在那里没有看到问题。 因此,非常感谢任何有关我哪里出错的帮助。

1。播放器模型类

@Data
@Entity
@Table(name="User_Player")
public class Player implements Serializable {

@OneToOne
private User user;
private static final long serialVersionUID = 1L;

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

private String playerName;
private String dob;
private String hometown;
private String weight;
private String height;
private Position position;



}

2。 PlayerStats 模型

@Data
@Entity
@Table(name="Player_Stats")


public class PlayerStats implements Serializable {

@ManyToOne
private Player player;


private static final long serialVersionUID = 1L;

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

private int td;
private int rushYards;
private int recYards;
private int returnYards;
private int throwingYards;
private int throwAttenpts;
private int throwSuccess;
private int receptions;
private int rushTD;
private int recTD;
private int fumbles;
private int fumblesRecovered;
private int forcedFumbles;
private int sacks;
private int puntsBlocked;
private int fgScored;
private int fgMissed;
private int punts;
private int tackle;

public Opponents opponents;
 }

3。 PlayerStats 控制器

@Slf4j
@Controller
@SessionAttributes("PlayerStats")
 public class PlayerStatsController {

 private PlayerStatsRepository playerStatsRepository;

 public PlayerStatsController(PlayerStatsRepository playerStatsRepository) 
{this.playerStatsRepository = playerStatsRepository;}

@Autowired
PlayerStatsRepository service;

@GetMapping("/addPlayerStats/{id}")
public String showSignUpFormPlayer(Player player) {
    return "addPlayerStats";
}

@PostMapping("/addPlayerStats/{id}")
public String processPlayer(@Valid PlayerStats playerStats, BindingResult result, 
 SessionStatus sessionStatus,
                            @AuthenticationPrincipal Player player, Model model) {
    if (result.hasErrors()) {
        return "playerStats";
    }

    //playerStats.setPl(player);
    service.save(playerStats);
    model.addAttribute("playerStats", service.findAll());
    return "login";
    }

4。用户模型

   @Entity
    @Data
    @NoArgsConstructor(access= AccessLevel.PRIVATE, force=true)
    @RequiredArgsConstructor
    public class User implements UserDetails {

    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy= GenerationType.AUTO)
    private Long id;
    private final String username;
    private final String password;
    //private final String fullname;


    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        return Arrays.asList(new SimpleGrantedAuthority("ROLE_USER"));
    }
    @Override
    public boolean isAccountNonExpired() {
        return true;
    }
    @Override
    public boolean isAccountNonLocked() {
        return true;
    }
    @Override
    public boolean isCredentialsNonExpired() {
        return true;
    }
    @Override
    public boolean isEnabled() {
        return true;
    }
  }

【问题讨论】:

  • 对于PlayerPlayerStats 之间的双向映射,您需要设置两个对象之间的链接。所以在你保存你的子对象PlayerStats 之前,只需将Player 的链接添加到它。 playerStats.setPlayer(player);
  • 我最初输入了那行并将其注释掉,我重新添加了它但仍然没有成功。也许我需要重建我的桌子?我也不需要在我的其他模型中使用那行代码。

标签: java mysql spring database jpa


【解决方案1】:

正如 Sariq 所说,您应该将Player 设置为 playerStats。

playerStats.setPlayer(player);

我还建议在 PlayerStats 类中明确声明外键。通过使用 @JoinColumn 注释来做到这一点,并确保使用数据库中的确切名称。

@ManyToOne
@JoinColumn(name = "player_id") // player_id has to match your foreign key in the database
private Player player;

【讨论】:

  • 我已经添加了该行,但它仍然没有填充我数据库中的 player_id 列。当我调试时,我可以看到该玩家的 id 被传递,但它仍然不会传播到数据库。我也尝试过@JoinColumn 方法,但还是不行。
  • 尝试在 @JoinColumn 中添加 nullable = false ,看看它是如何工作的/你可能会遇到什么异常。
  • 不,也不起作用。这是我在对此进行调试时看到的内容(在下面的 cmets 中): playerStats.setPlayer(player); // Player = null
  • 那么这似乎是问题所在。您设置为 PlayerStats 的玩家实体为 null,因此外键也为 null。
  • 但除了显示“Player = null”之外,它还显示“id = 11”,这是我添加统计信息的玩家的正确 ID。那么为什么它会选择 id 而不是实际的玩家呢?我将如何改变它?
【解决方案2】:

所以我想出了问题所在。 @AuthenticationPrincipal 注释导致错误。我相信应该使用 userDetailsS​​ervice 方法为用户获取数据。当我删除代码按预期工作时。谢谢!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多