java - Hibernate一对一处理两列(实体类中相同类型的两个字段)

标签 java hibernate hibernate-mapping

假设我有一个圈和十字游戏(井字游戏):

游戏:

id    crosses_player_id    noughts_player_id...

玩家:

id    alignment    game_id

由于只有 2 个玩家,我认为没有必要创建一个单独的表,所以我这样做了:

@Entity
@Table(name = "games")
public class Game {
    @Id @GeneratedValue
    private int id;

    @OneToOne(mappedBy = "game")
    @JoinColumn(name = "crosses_player_id")
    private Player crossesPlayer;
    @OneToOne(mappedBy = "game")
    @JoinColumn(name = "noughts_player_id")
    private Player noughtsPlayer;

    private List<Move> moves = new ArrayList<>();
    private List<Field> fields = new ArrayList<>();
...
@Entity
@Table(name = "players")
public class Player {
    @ManyToOne
    @JoinColumn(name="user_id", nullable=false)
    private User user;

    private enum Alignment {
        NOUGHTS, CROSSES
    };
    private Alignment alignment;

    @OneToOne(mappedBy = ?)
    private Game game;
...

但是我不确定要在 Player 类的 @OneToOne(mappedBy = ?) 中放入什么内容。

我找到的最接近的答案是这个:

https://stackoverflow.com/a/13944195/4759176

class TeamPlay {
    @ManyToOne
    Team homeTeam;

    @ManyToOne
    Team awayTeam;
}

class Team {
    @OneToMany(mappedBy="homeTeam")
    Set<TeamPlay> homeTeamPlays;

    @OneToMany(mappedBy="awayTeam")
    Set<TeamPlay> awayTeamPlays;
}

但是看起来 Team 类可以有许多可能的游戏,而在我的例子中,1 个玩家只能玩 1 场游戏。玩家基本上是用户的 ID、游戏的 ID 和排列(圈或叉),游戏结束后,任何新游戏都不会再引用同一玩家。也许我应该这样做:

玩家:

@OneToOne(mappedBy = "crossesPlayer")
private Game crossesGame;

@OneToOne(mappedBy = "noughtsPlayer")
private Game noughtsGame;

但是,玩家只能是零或十字玩家,所以这些字段之一将始终为空?

最佳答案

@parsecer ...对我来说,您的问题在于对数据模型的误解;引用你的话:

A player is basically users's id, game's id and the allighment (noughts or crosses) and after the game is over that same player is never referenced again from any new games

这意味着“游戏”是一个强大的实体,不应该有对玩家的引用(即外键)(即表“游戏”不应包含以下列:crosses_player_id,noughts_player_id)...这也意味着“玩家”是一个弱实体,仅存在于“游戏”的上下文中(因此,这里可以有一个外国游戏专栏)...

假设所有这些,您的模型和映射都会变得更清晰,例如:

@Entity
@Table(name = "players")
public class Player {
    /**
     * Player's ID.
     */
    @Id
    private int id;

    /**
     * Game to which this Player belongs.
     */
    @ManyToOne(optional = false)
    @JoinColumn(name = "game_id", nullable = false, updatable = false)
    private Game game;

    /**
     * Player's alignment in the game.
     */
    @Enumerated(EnumType.STRING)
    private Alignment alignment;
}

@Entity
@Table(name = "games")
public class Game {
    /**
     * Game's Id.
     */
    @Id
    private int id;

    /**
     * Players in this game.
     */
    @OneToMany(mappedBy = "game", cascade = PERSIST)
    @MapKey(name = "alignment")
    private Map<Alignment, Player> players = new HashMap<>();

    ...

    public List<Player> getPlayers() {
        return Arrays.asList( this.players.values() );
    }

    public Player getCrossesPlayer() {
        return this.players.get(Alignment.CROSSES);
    }

    public Player getNoughtesPlayer() {
        return this.players.get(Alignment.NOUGHTES);
    }
}

关于java - Hibernate一对一处理两列(实体类中相同类型的两个字段),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60130916/

相关文章:

java - Spring Hibernate 类映射问题

java - 为什么 Hibernate 生成一个连接错误列的查询?

java - 中间表和非主键的一对一映射

java - 在jsonpath中过滤时如何获取第一个元素?

Java播放错误的声音频率

java - 意外的 AST 节点 : < on update query

sql - 寻找下一个空闲时间段

java - 是否有任何选项可以使用 Spring-AMQP 在 RabbitMQ 中设置 AutomaticRecoveryEnabled?

java - 如何获取List的类变量

java - Hibernate SchemaExport 和持久化单元