我整天都被困住了。我有一个向API进行POST的表单,我希望将数据保存到3个表中。

  • 记录保存在一个具有自动生成的ID的表( Squad )中。在此表中插入时,我想读取自动生成的记录ID并将其插入其他表中( SquadPlayers ),还要插入该表单在第二个表中提交的额外字段( SquadPlayers :GenericPlayerId) 。
  • 还有一些关于我想从前端表单提交的内容。我希望提交有关该小队以及最多11名球员的ID的所有信息(这些ID是我想要保存在 SquadPlayers 表的GenericPlayerId字段中的内容)。

  • 我是后端编码的新手,尤其是数据库,我出于学习目的选择了这个新堆栈,因此,如果您在这里看到任何愚蠢的东西,现在您知道为什么:-)如果您认为我完全不赞成或不赞成我的数据库设计,请允许我知道。
    java - 在Hibernate的多个表中插入数据-LMLPHP

    到目前为止,我在Squad和SquadPlayers的两个类中都有此功能。

    Squad.java
    package com.FUT.track.web.FUTtrackapplication.squads;
    
    import javax.persistence.*;
    
    @Entity
    @Table(name="Squad")
    public class Squad {
    
        @Id
        @GeneratedValue( strategy = GenerationType.IDENTITY )
        private int squadId;
        private String squadName;
        private String squadDescription;
        private String primaryFormation;
    
        @OneToOne(cascade = CascadeType.ALL)
        @JoinColumn(name = "playerId")
        private SquadPlayers squadPlayers;
    
    
        public Squad() {
    
        }
    
        public Squad(String squadName, String squadDescription, String primaryFormation, SquadPlayers squadPlayers) {
            super();
            this.squadName = squadName;
            this.squadDescription = squadDescription;
            this.primaryFormation = primaryFormation;
            this.squadPlayers = squadPlayers;
    
        }
    
        public int getSquadId() {
            return squadId;
        }
    
        public void setSquadId(int squadId) {
            this.squadId = squadId;
        }
    
        public String getSquadName() {
            return squadName;
        }
    
        public void setSquadName(String squadName) {
            this.squadName = squadName;
        }
    
        public String getSquadDescription() {
            return squadDescription;
        }
    
        public void setSquadDescription(String squadDescription) {
            this.squadDescription = squadDescription;
        }
    
        public String getPrimaryFormation() {
            return primaryFormation;
        }
    
        public void setPrimaryFormation(String primaryFormation) {
            this.primaryFormation = primaryFormation;
        }
    
        public SquadPlayers getSquadPlayers() {
            return squadPlayers;
        }
    
        public void setSquadPlayers(SquadPlayers squadPlayers) {
            this.squadPlayers = squadPlayers;
        }
    
    }
    

    SquadPlayers.java
     package com.FUT.track.web.FUTtrackapplication.squads;
    
    import javax.persistence.*;
    
    @Entity
    @Table(name="SquadPlayers")
    public class SquadPlayers {
    
        @Id
        private Integer playerId;
        private Integer squadId;
        private Integer genericPlayerId;
    
        @OneToOne(mappedBy = "squadPlayers")
        private Squad squad;
    
        public Integer getPlayerId() {
            return playerId;
        }
    
        public void setPlayerId(Integer playerId) {
            this.playerId = playerId;
        }
    
        public Integer getSquadId() {
            return squadId;
        }
    
        public void setSquadId(Integer squadId) {
            this.squadId = squadId;
        }
    
    
        public Squad getSquad() {
            return squad;
        }
    
        public void setSquad(Squad squad) {
            this.squad = squad;
        }
    
        public Integer getGenericPlayerId() {
            return genericPlayerId;
        }
    
        public void setGenericPlayerId(Integer genericPlayerId) {
            this.genericPlayerId = genericPlayerId;
        }
    
    }
    

    最佳答案

    假设这就是您要执行数据流的方式

  • 您已经预定义了player列表。并且player可以属于多个小队
  • 您将通过向表单提交分配squad来在表单提交上创建player。并且分配的玩家将具有唯一的标识号。
  • 每个squadPlayer都会有playerStat

  • 注意:
  • PlayerSquad之间的关系是 ManyToMany
  • 您的SquadPlayerPlayerSquad之间的联接表
  • 因此,PlayerSquadPlayer之间的关系为 OneToMany
  • SquadSquadPlayer之间的关系为 OneToMany

  • 播放器
    @Entity
    @Table(name = "player")
    public class Player {
    
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private int id;
        private String name;
        private String position;
        private String country;
        private String club;
    
        @OneToMany(mappedBy = "player")
        private Set<SquadPlayer> squadSet = new HashSet<>();
    
        ....
    }
    

    在这里,您的Player实体具有squadSet字段的 OneToMany 关联,该字段描述了一个球员可以被包括在多个阵容中的事实。

    小队
    @Entity
    @Table(name="squad")
    public class Squad {
    
        @Id
        @GeneratedValue( strategy = GenerationType.IDENTITY )
        private int id;
        private String name;
        private String description;
        private String primaryFormation;
    
        @OneToMany(mappedBy = "squad", cascade = {CascadeType.MERGE, CascadeType.PERSIST})
        private Set<SquadPlayer> playerSet = new HashSet<>();
    
        ...
     }
    

    此处Squad实体具有 OneToMany playerSet字段的关联,描述一个小队可能有多个玩家。请注意,与此处的Player实体不同, OneToMany 批注定义了MergePersist的级联类型。这告诉hibernate在持久化Squad时也要持久化此关系

    SquadPlayer
    @Entity
    @Table(name = "squad_player")
    public class SquadPlayer {
    
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private int id;
    
        @Column(name = "generic_player_id")
        private int genericPlayerId;
    
        @ManyToOne
        @JoinColumn(name = "squad_id")
        private Squad squad;
    
        @ManyToOne
        @JoinColumn(name = "player_id")
        private Player player;
    
        @OneToOne(mappedBy = "squadPlayer", orphanRemoval = true, cascade = CascadeType.ALL)
        private PlayerStat playerStat;
    
        ...
    }
    

    只需在此处为PlayerSquad映射的另一端以及相应的连接列即可

    现在,您的PlayerStat实体具有与 SquadPlayer OneToOne 关系。删除orphanRemoval=true后,拥有PlayerStat将从SquadPlayer中删除该条目(尽管它是可选的)。我们还为此关系定义了级联规则。

    PlayerStat
    @Entity
    @Table(name = "player_stat")
    public class PlayerStat {
    
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private int id;
        private int performance;
    
        @OneToOne
        @JoinColumn(name = "squad_player_id")
        private SquadPlayer squadPlayer;
        ...
    }
    

    坚持小组与所有这些关系

    请记住,JPA或Hibernate确定与对象图的数据库关系。实体从定义其关联的过程中一直与级联关系保持一致。因此,您可以按照以下流程为Squad对象进行适当的关联
  • 创建一个new Squad()并使用提供的字段设置所有字段。
  • 从表单中获得玩家ID列表后,将这些player对象拉入同一笔交易
  • 迭代所有这些player并为每个new SquadPlayer()创建PlayerStat。设置所有关联的字段以及SquadPlayer字段。然后将每个Squad添加到playerSet对象的Squad字段中。
  • 最后持久化ojit_code对象

  • 如果遵循此流程中的所有内容,则数据库应使用适当的关系填充所有表。

    供进一步阅读:
  • 了解关系映射,请参见OneToManyManyToManyManyToOneOneToOne快速指南
  • JPA and Hibernate Cascade Types开头的好文章
  • 关于Cascading Best Practices的另一篇好文章
  • 10-07 15:39