2016-04-01 18 views
0

Ich habe 2 Klassen Regel und Gruppe. Eine Regel wird mehreren Gruppen über eine andere Klasse RuleGroupMap zugeordnet. Die entsprechenden Tabellen in DB sind wie folgtHibernate Mapping Composite-Primärschlüssel, der Fremdschlüssel enthält

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`) 
) 

Die RuleGroupMap seine PK als Kombination von Regel-Kennzeichnung und group_id hat. Außerdem hat rule_id eine ManyToOne-Beziehung zu Rule und group_id hat eine ManyToOne-Beziehung zu Group.

Wie erstelle ich Entitäten in Hibernate für dieses Szenario?

Mein aktueller Code ist wie folgt und löst eine SQLGrammerException aus.

@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; 
} 

Antwort

0

Verwenden MapId Anmerkung auf Ihrer RuleMap Klasse. Sie werden auch besser mit @Embeddable und @EmbeddedId arbeiten, da sie neuer und vom JPA-Provider empfohlen werden. Siehe How to create a composite primary key which contains a @ManyToOne attribute as an @EmbeddedId in JPA?. und How to map compound primary key in JPA, where part of Primary Key is a Foreign Key.

+0

Danke! Das hat für mich funktioniert. –

+0

Ich habe eine Follow-up-Frage dazu. Ich habe jetzt eine @Embedded-Eigenschaft namens map in meiner RuleGroupMap-Klasse, die auf meine PK verweist (mit Group_id und Rule_id). Ich habe auch eine andere Eigenschaft in der gleichen Klasse des Typs Regel. Wenn ich ein neues Objekt von RuleGroupMap erstelle, sollte ich sowohl die Rule-Eigenschaft als auch die map.rule_id-Eigenschaft oder nur die Rule-Eigenschaft festlegen? –

+0

Ich denke, ich verstehe die Frage. Siehe zweiten Link der Antwort, in der Nähe des unteren Randes befindet sich Code zur Verwendung dieser Art von PK. Ich denke, die Antwort für Sie ist, nur die Rule-Eigenschaft zu setzen, da es sich um die 'MapsId'-Annotation handelt: Sie legt die map.rule_id für Sie fest. –

0

In Ihrem @IdClass Sie haben keine Spaltennamen zu erklären, nur erklären:

public class RuleMapPK implements Serializable { 

    private static final long serialVersionUID = 1L; 

    private long group; 
    private Long rule; 

    //getter & setter - equals & hashcode 
}