在Hibernate中的多个表中插入数据

时间:2017-11-12 01:37:10

标签: java hibernate jpa

我整天都被困在这一天。我有一个表单对API进行POST,我希望将数据保存到3个表中。

  1. 记录保存在一个具有自动生成ID的表格中( Squad )。在此表中插入时,我想读取自动生成的记录ID并将其插入到不同的表( SquadPlayers )中,另外还插入由第2个表格中的表单提交的额外字段(< strong> SquadPlayers : GenericPlayerId )。
  2. 还有一点关于我想从前端表单提交的内容。我想要提交最多11名球员的球队加上Ids的所有信息(这些ID是我希望在 SquadPlayers 表中提交的 GenericPlayerId 字段中保存的)。
  3. 我是后期编码的新手,特别是数据库和我为了学习目的而选择的这个新堆栈,所以如果你在这里看到任何愚蠢的东西,现在你知道为什么:-)所以如果你认为我完全关闭或错了我的数据库设计让我知道。 enter image description here

    到目前为止,我在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;
        }
    
    }
    

1 个答案:

答案 0 :(得分:6)

假设您希望如何执行数据流

  • 您有预定义的player列表。 player可以属于多个小队唯一
  • 您将通过为表单提交squad来为表单提交创建player。指定的玩家将拥有唯一的识别码。
  • 每个squadPlayer都有playerStat

注意:

  • PlayerSquad之间的关系为 ManyToMany
  • SquadPlayerPlayer
  • 之间的Squad加入表
  • 因此,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实体与playerSet字段的 OneToMany 关联描述了一个Squad可能有多个玩家。请注意,与Player实体不同, OneToMany 注释定义了MergePersist的级联类型。当持久化Squad时,这会告诉hibernate 持久存在这种关系

<强> 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被移除时,PlayerStatSquadPlayer删除该条目(尽管可选)。我们还为此关系定义了级联规则。

<强> 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字段。
  • 最后坚持<input autocomplete="off" class="autocomplete-hint select" data-auto-complete-minlength="1" type="text" onFocus="searchCountry(this)"> <script type="text/javascript"> function searchCountry(a) { $(function() { var cache = {}; $(a).autocomplete({ appendTo: ".countrys", change: function (event, ui) { if (ui.item == null || ui.item == undefined) { $(a).val(""); $(a).empty(); $(a).next("#loading").hide(); } else { var position = $(".countrys").position(), left = position.left, top = position.top; $(".countrys > ul").css({ left: left + 20 + "px", top: top + 4 + "px" }); } }, minLength: 1, select: function (event, ui) { // Set autocomplete element to display the label this.value = ui.item.label; $(this).closest("tr").find(".countryid").val(ui.item.hotelid); $(this).closest("tr").find(".countryid").next(".countryid").val(ui.item.hotelid); // Store value in hidden field $('#hidden_field').val(ui.item.id); $('#hidden_field1').empty().text(ui.item.label); // Prevent default behaviour return false; }, source: function( request, response ) { $(a).next("#loading").show(); var term = request.term; if (term in cache) { response(cache[term]); return; } $.getJSON( "jsonloadi.bc", request, function( data, status, xhr ) { $(a).next("#loading").hide(); cache[ term ] = data; response( data ); }); } }); }); } </script> 对象

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

进一步阅读: