Java 使用hibernate进行Spring引导:创建复合键和多对多关系

Java 使用hibernate进行Spring引导:创建复合键和多对多关系,java,spring-boot,hibernate,orm,composite-key,Java,Spring Boot,Hibernate,Orm,Composite Key,我试图创建一个非常简单的Spring Boot应用程序来存储体育数据 它有两个实体:玩家和锦标赛。但是,我想存储每个球员在每个锦标赛中的排名 为此,我创建了下面的ER图。连接表PlayerPlacement\u map包含一个关系属性placement,用于存储玩家在锦标赛中的位置: 关于如何映射玩家和锦标赛之间的关系,我遵循了本指南,将这两个表中的Id作为名为PlayerPlacementMap的连接表中的复合键: 这给了我以下的课程: Player.java(Tournament.java

我试图创建一个非常简单的Spring Boot应用程序来存储体育数据

它有两个实体:玩家和锦标赛。但是,我想存储每个球员在每个锦标赛中的排名

为此,我创建了下面的ER图。连接表
PlayerPlacement\u map
包含一个关系属性
placement
,用于存储玩家在锦标赛中的位置:

关于如何映射玩家和锦标赛之间的关系,我遵循了本指南,将这两个表中的Id作为名为
PlayerPlacementMap
的连接表中的复合键:

这给了我以下的课程:

Player.javaTournament.java遵循类似的模式-为简洁起见省略)

PlayerPlacement.java(连接表)

我有关于球员、锦标赛和球员替换的存储库。玩家和锦标赛存储库本身运行良好,我能够通过@RestController对MSSQL数据库执行CRUD操作

这是playerplacement的存储库:

@Repository
public interface PlayerPlacementRepository extends JpaRepository<PlayerPlacement, PlayerPlacementKey> 
{}
最后,问题来了:当我调用
/“playerplacement”
端点时,我收到以下错误

@RestController
public class PlayerPlacementController {

    @Autowired
    private PlayerPlacementRepository playerPlacementRepository;

    @PostMapping("/playerplacement")
    public PlayerPlacement addPlayerPlacement(@RequestBody PlayerPlacement playerPlacement) {
    return playerPlacementRepository.save(playerPlacement);
    }
}
org.hibernate.id.IdentifierGenerationException: null id generated for:class com.testproject.learning.model.PlayerPlacement
我想我已经迁移了数据库,但为了安全起见,以下是我对连接表的迁移:

CREATE TABLE PlayerPlacement_map (

PlayerId Bigint NOT NULL,
TournamentId Bigint NOT NULL,
Placement int

CONSTRAINT PK_PlayerPlacement NOT NULL IDENTITY(1,1) PRIMARY KEY
(
    PlayerId,
    TournamentId
)

FOREIGN KEY (PlayerId) REFERENCES Players (Id),
FOREIGN KEY (TournamentId) REFERENCES Tournaments (Id)
);
我还没有弄清楚我做错了什么。我感谢所有的帮助和指点,我收到-提前感谢

编辑: 在用户Alex V的帮助下取得了进展,但我现在遇到了一个新问题。

我进行以下JSON调用:

{
    "player": 
    {
        "name":"John Winther"
    },
    "tournament": 
    {
        "name":"Spring Boot Cup 2020"
    },
    "placement":3
}
我自己没有设置
id
(复合键)-我想应该由框架的某个部分来处理它?无论如何,当我在调试模式下进行此调用时,我会在端点中设置以下调试变量

但是,它会导致以下错误

@RestController
public class PlayerPlacementController {

    @Autowired
    private PlayerPlacementRepository playerPlacementRepository;

    @PostMapping("/playerplacement")
    public PlayerPlacement addPlayerPlacement(@RequestBody PlayerPlacement playerPlacement) {
    return playerPlacementRepository.save(playerPlacement);
    }
}
org.hibernate.id.IdentifierGenerationException: null id generated for:class com.testproject.learning.model.PlayerPlacement
java.lang.NullPointerException:无法调用“Object.getClass()”,因为“o”为null
,这可能是指
PlayerPlacementKey.java
(?)中我的
equals
-方法:


希望任何人都能再次将我推向正确的方向。

您的实体有
playerId
字段,注释为
@Column(name=“Player\u Id”)
,但数据库表包含
playerId
列,而不是
playerId
。与
tournamentId
player
tournament
字段的情况相同

@MapsId(“TournamentId”)
必须包含
@embeddedid
类字段名
TournamentId
,而不是
TournamentId
。这意味着该字段由嵌入的id字段映射
tournamentId

@ManyToOne
@MapsId("tournamentId")
@JoinColumn(name = "tournamentId")
Tournament tournament;

这里也有同样的问题
@MapsId(“PlayerId”)

你好,alex,很抱歉反应太晚,我到现在还没找到。对于您答案的第一部分,我了解到,在每个名称为“锦标赛id”或“球员id”的列中,我将其更改为与数据库匹配,但不带下划线,例如“锦标赛id”?对于问题的第二部分,您的意思是我应该在PlayerPlacement.java中的锦标赛和玩家字段中添加@EmbeddedId(“tournamentId”)。在这种情况下,我有四个注释。而且,它给了我一个错误,当我这样做。我想知道你是否有任何文件可以参考或类似?谢谢。另外,在Player.java中,我定义了一个名为placements的
@OneToMany
映射。我甚至需要这个,因为我已经在它上面做了一个
@manytomy
地图吗?我已经在第二部分编辑了添加答案的示例。嗨,亚历克斯,再次感谢你回复我并添加更多信息。它把我推向了正确的方向!现在我能够正确地调用端点并设置一些变量。然而,我面临着一个新的问题:我在原来的帖子中添加了一个描述,从我添加了EDIT-tag的老帖子的底部开始。我希望你愿意再看一次。我非常感谢到目前为止的帮助,希望再次收到您的回复。您应该添加:
if(null==o)return false
in
equals
methodHey@alexvaluiskyi非常感谢。我试图将它添加到
equals
-方法的第一行,但不幸的是,它返回了相同的错误消息。不过我真的很感谢你的帮助,非常感谢。据我所知,你试图将
PlayerPlacement
包含
Player
锦标赛
保存到数据库中?如果是这样,您必须为每个关系添加一个适当的级联参数:。@alexvaluiskyi再次感谢Alex。我将仔细查看文档。我感谢你给我的所有帮助
@Override
public boolean equals(Object o) {
    if (this == o) return true;
    if (!(o instanceof PlayerPlacementKey)) return false;
    PlayerPlacementKey that = (PlayerPlacementKey) o;
    return playerId == that.playerId &&
            tournamentId == that.tournamentId;
}
@ManyToOne
@MapsId("tournamentId")
@JoinColumn(name = "tournamentId")
Tournament tournament;