JPA:基于“自然键”合并实体

时间:2014-02-24 12:57:50

标签: java mysql hibernate jpa

可能我理解错误的概念,但这是我的问题:

我想在我的数据库中存储两种类型的数据:

  1. 游戏位置(由一些冗长的字符串唯一表示,包含两个移动列表 - 一个用于在此位置移动,一个用于移动到此位置)
  2. 游戏移动(用较小的字符串表示,连接两个位置)
  3. 在课堂上:

    @Entity
    public class Move {
        @Id
        @GeneratedValue
        private long id;
        private String representation;
        private Position positionBeforeMove;
        private Position positionAfterMove;
    
        ...
    }
    
    @Entity 
    public class Position {
        @Id
        private String representation;
        private List<Move> movesLeadingToPosition;
        private List<Move> movesLeadingFromPosition;
    
        ...
    }
    

    我想存储一组游戏。在此上下文中,位置是唯一的,并且移动可能在数据库中多次出现。

    我的naieve实现使用两个表:

    MOVE
    number   id                    (PK)
    varchar2 representation
    varchar2 positionBeforeMove    (FK)
    varchar2 positionAfterMove     (FK)
    ...
    
    POSITION
    varchar2 representation        (PK)
    ...
    

    这很好用;使用EntityManager.merge(position)我可以在存储越来越多的游戏时增加我的POSITION表,同时保持位置的独特性。

    然而,解决方案并不是最优的:我更喜欢在MOVE表中生成id生成的@Entity public class Position { @Id @GeneratedValue private long id; private String representation; private List<Move> movesLeadingToPosition; private List<Move> movesLeadingFromPosition; ... } MOVE number id (PK) varchar2 representation number positionBeforeMove_id (FK) number positionAfterMove_id (FK) ... POSITION number id; (PK) varchar2 representation (Unique) ...

    EntityManager.merge(...)

    但是当我实现这个时,我最终得到了重复的表示,因为positionAfterMove基于指定的 ID合并,而不是自然键。< / p>

    有什么方法可以让java(JPA / Hibernate / ...)基于自然键合并位置,同时还允许我使用ID作为表的键?或者,我需要手动合并头寸吗? (例如:每当我想存储移动时,我是否需要从数据库中检索positionBeforeMovemovesLeadingToPosition,分别将移动添加到movesLeadingFromPosition和{{1}},然后更新数据库中的位置?)

    (上下文:我正在使用Java 1.7,JPA和MySQL数据库)

1 个答案:

答案 0 :(得分:1)

不,不可能; merge()使用实体密钥(@Id目标)完成。

可能需要按照JPA equivalent to Hibernate's @NaturalId中的说明添加@NaturalId或模仿,并使用业务方法检查重复插入