【问题标题】:Hibernate Mapping composite primary key that contains foreign keysHibernate Mapping 包含外键的复合主键
【发布时间】:2016-04-01 15:04:19
【问题描述】:

我有 2 个类规则和组。一个规则通过另一个类 RuleGroupMap 映射到多个组。 DB中对应的表是这样的

CREATE TABLE `rules` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `validity_start_time` timestamp NULL DEFAULT NULL,
  `validity_end_time` timestamp NULL DEFAULT NULL,
  `rule_name` char(25) DEFAULT '',
  `description` text,
  PRIMARY KEY (`id`)
)

CREATE TABLE `group` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(200) NOT NULL
  PRIMARY KEY (`id`)
)

CREATE TABLE `rule_group_map` (
  `area_id` int(11) NOT NULL DEFAULT '0',
  `group_id` bigint(11) NOT NULL DEFAULT '0',
  `active` tinyint(1) DEFAULT NULL,
  PRIMARY KEY (`group_id`,`rule_id`),
  KEY `group` (`group_id`),
  KEY `rule` (`rule_id`),
  CONSTRAINT `group` FOREIGN KEY (`group`) REFERENCES `group` (`id`),
  CONSTRAINT `rule` FOREIGN KEY (`rule_id`) REFERENCES `rules` (`id`)
)

RuleGroupMap 的 PK 是 rule_id 和 group_id 的组合。此外,rule_id 与 Rule 具有 ManyToOne 关系,group_id 与 Group 具有 ManyToOne 关系。

如何在 Hibernate 中为此场景创建实体?

我当前的代码如下并抛出一个 SQLGrammerException。

@Entity
@Table(name = "rules")
public class Rule implements Serializable{

    @Id @GeneratedValue(strategy = IDENTITY)
    @Getter @Setter @Column(name = "id", nullable = false, unique = true)
    private Long Id;

    @Getter @Setter @Column(name = "validity_start_time", nullable = false)
    private Timestamp validity_start;

    @Getter @Setter @Column(name = "validity_end_time", nullable = false) 
    private Timestamp validity_end;

    @Getter @Setter @Column(name = "rule_name") 
    private String ruleName;

    @Getter @Setter @Column(name = "description") 
    private String description;

    @Getter @Setter @OneToMany(mappedBy = "rule") 
    private Set<RuleGroupMap> groupsMap;
}



    @Entity
    @Table(name = "group")
    public class Group implements Serializable {

        @Id
        @Getter @Setter @Column(name = "id", nullable = false) 
        private long id;

        @Getter @Setter @Column(name = "name", nullable = false) 
        private String name;

        @Getter @Setter @OneToMany(mappedBy = "area") 
        private Set<RuleGroupMap> rulesMap;
    }


@Entity
@Table(name = "rule_group_map")
@Data
@IdClass(RuleMapPK.class)
public class RuleGroupMap {

    @Id @ManyToOne @JoinColumn(name="group_id", referencedColumnName = "id") private Group group;

    @Id @ManyToOne @JoinColumn(name="rule_id", referencedColumnName = "id") private Rule rule;

    @Column(name = "active") private boolean active;
}

@Data
public class RuleMapPK implements Serializable {
    @Column(name="group_id") long group;
    @Column(name="rule_id") Long rule;
}

【问题讨论】:

    标签: jpa


    【解决方案1】:

    RuleMap 类上使用 MapId 注释。使用@Embeddable@EmbeddedId 也会更好,因为它们较新且由JPA 提供商推荐。请参阅How to create a composite primary key which contains a @ManyToOne attribute as an @EmbeddedId in JPA?.How to map compound primary key in JPA, where part of Primary Key is a Foreign Key

    【讨论】:

    • 我对此有一个后续问题。我现在在我的 RuleGroupMap 类中有一个名为 map 的 @Embedded 属性,它链接到我的 PK(带有 Group_id 和 Rule_id)。我在同一类规则中还有另一个属性。当我创建 RuleGroupMap 的新对象时,我应该同时设置 Rule 属性和 map.rule_id 属性还是只设置 Rule 属性?
    • 我想我理解这个问题。请参阅答案的第二个链接,底部附近是使用此类 PK 的代码。我认为您的答案是仅设置 Rule 属性,因为这就是 MapsId 注释的含义:它为您设置 map.rule_id。
    • 谢谢!正是我想要的。
    【解决方案2】:

    在您的@IdClass 中,您无需声明列名,只需声明:

    public class RuleMapPK implements Serializable {
    
        private static final long serialVersionUID = 1L;
    
        private long group;
        private Long rule;
    
        //getter & setter - equals & hashcode
    }
    

    【讨论】:

      猜你喜欢
      • 2018-01-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-10-06
      • 2018-02-02
      • 2020-02-19
      • 2015-08-31
      相关资源
      最近更新 更多