JPA / Hibernate OneToMany Mapping, using a composite PrimaryKey

27.8k Views Asked by At

I'm currently struggling with the right mapping annotations for a scenario using a composite Primary Key Class. First, what I am trying to achieve in words:

I have 2 classes: group and FieldAccessRule. A Group can have many FieldAccessRules, while a FieldAccessRule only has ONE Group assigned. Modling this is not a problem so far (simplified):

public class Group{
    ...
    @OneToMany(mappedBy = "group")
    private Set<FieldAccessRule> fieldAccessRules;
    ... 
}

and for the FieldAccessRule:

public class FieldAccessRule {
    ...
    @ManyToOne
    @JoinColumn(name = "group_id")
    private Group group;
    ...
}

Now, I decided to use a Composite PK for the FieldAccessRule, because a Rule should be unique for ONE Group and ONE Field. It looks like this:

@Embeddable
public class FieldAccessRulePK implements Serializable{
    private String fieldKey;
    private Group group;
    ...
}

And ofc. the FieldAccessRule needs to change to

public class FieldAccessRule {
    ...
    @EmbeddedId
    private FieldAccessRulePK fieldAccessRulePK;
    ...
}

How do I create the right Mapping for the FieldAccessRuleSet of Group now? Doing it like this, I get :

In attribute 'fieldAccessRules', the "mapped by" value 'group' cannot be resolved to an >attribute on the target entity.

Whats the right way of creating the mapping from Group to A PART of the PrimaryKey?

Edit: I know found out, that using

public class Group{
    ...
    @OneToMany(mappedBy = "fieldAccessRolePK.group")
    private Set<FieldAccessRule> fieldAccessRules;
    ... 
}

is EXACTLY working as expected. It compiles fine, it creates the DB fine and after loading a group with predefined Roles, they are available as expected.

However, Eclipse still says

In attribute 'fieldAccessRules', the "mapped by" value 'fieldAccessRulePK.group' cannot be resolved to an attribute on the target entity.

Im not sure, if it's good to ignore Error and "assume" everythings fine... (I found a post, where it has been said, that a mapping of the pattern attr1.attr2 is supported by Hibernate but not JPA-confirm.)

2

There are 2 best solutions below

2
On

In your code, EntityManager cannot resolve mappedBy attribute fieldAccessRulePK.group.

Reason

EntityManager assume that FieldAccessRule entity have an attribute name with fieldAccessRulePK.group during the FieldInjection.

According to Java Naming Variables Rule, you cannot name fieldAccessRulePK.group by using characters dot > '.'

Java Naming Variables Rule Reference

All variable names must begin with a letter of the alphabet, an underscore ( _ ), or a dollar sign ($). The rest of the characters may be any of those previously mentioned plus the digits 0-9. The convention is to always use a letter of the alphabet. The dollar sign and the underscore are discouraged.

One more thing:

Don't use group instance in your FieldAccessRulePK embeddable class. For more reference here.

Try as below :

@Embeddable
public class FieldAccessRulePK implements Serializable{
    @Column(name = "FIELD_KEY")
    private String fieldKey;
    @Column(name = "GROUP_ID")
    private String groupId;
}

public class FieldAccessRule {
    @EmbeddedId
    private FieldAccessRulePK id;

    @ManyToOne
    @JoinColumn(name = "GROUP_ID", referencedColumnName = "ID")
    private Group group;
}


public class Group{
    @OneToMany(mappedBy = "group")
    private Set<FieldAccessRule> fieldAccessRules;
}
0
On

I've fixed a similar problem by modifying the mappedBy attribute of the parent class (using dotted notation)

public class Group{
    ...
    @OneToMany(mappedBy = "fieldAccessRulePK.group")
    private Set<FieldAccessRule> fieldAccessRules;
    ... 
}

and by keeping the annotations in the PK class:

@Embeddable
public class FieldAccessRulePK implements Serializable{
    private String fieldKey;

    @ManyToOne
    @JoinColumn(name = "group_id")
    private Group group;
    ...
}