I would like to create a unidirectional @ManyToMany between Account entity and Pushable interface. Pushable is just a marker interface implemented by two classes: Package and Plan
Package is a simple entity:
@Entity
public class Package extends BasicEntity{
}
but Plan is an embedded object placed inside the Service entity:
@Entity
public class Service extends BasicEntity{
@Embedded
Plan plan;
}
BacicEntity provides ID for it's childern:
@MappedSuperclass
public abstract class BasicEntity{
@Id
@GeneratedValue(strategy = IDENTITY)
@Column(name = "ID")
protected Long id;
}

My mapping looks like this:
@Entity
public class Account extends Basicentity{
@ManyToMany(cascade=CascadeType.ALL)
@JoinTable(name="PUSHABLES_ACCOUNTS", joinColumns=@JoinColumn(name="ID"),
inverseJoinColumns=@JoinColumn(name="ID"))
private List<Pushable>pushables = new ArrayList<Pushable>();
}
My main concerns are:
would a mapping between an Entity and an Interface even work? (in general)
The JPA Specification defines relationships between entities. The JPA Spec s 2.1 states interfaces must “not be designated as an entity”. So Pushable cannot be the target for a relationship in any portable way.
Further, your Plan object is an embedded object and not an entity in its own right and also cannot be the target of a relationship.
would it be a problem to have two ID columns in a join table? Both Account and Service get @Id from BasicEntity
There is a principle issue with the @JoinTable you have set up regardless of the fact that an interface is the target.
@ManyToMany(cascade=CascadeType.ALL)
@JoinTable(name="PUSHABLES_ACCOUNTS", joinColumns=@JoinColumn(name="ID"),
inverseJoinColumns=@JoinColumn(name="ID"))
In @JoinColumn(name="ID"), ‘name’ refers to the name of the column in the link table PUSHABLES_ACCOUNTS, this is also true for inverseJoinColumns=@JoinColumn(name="ID"))
So, (and ignoring the fact that Pushables is not an entity), your joinColumns and inverseJoinColumns refer to the same column in the PUSHABLES_ACCOUNTS link table. You need to link the ID of the Account, to the ID of the Pushable.
You would expect a join table to look something like the following:
PUSHABLES_ACCOUNTS
**Account_ID** **PUSHABLES_ID**
005 017
…. ….
Therefore your join table would be:
@ManyToMany(cascade=CascadeType.ALL)
@JoinTable(name="PUSHABLES_ACCOUNTS",
joinColumns=@JoinColumn(name=" Account_ID ", referencedColumnName=”ID”),
inverseJoinColumns=@JoinColumn(name=" PUSHABLES_ID " , referencedColumnName=”ID”))
I’ve added referencedColumnName here, although these values would be used by default. These are the columns of the source table (joinColumns) and target table (inverseJoinColumns). It is possible for this relationship to be self referencing and for the source table = target table.
Options
The only possible relationship targets from Account in your current class diagram are therefore Package and Service. So you could define Two ManyToMany relationships from Account – one to Package and one to Service. Then dig out the embedded Plan from each of the Service entities and build the list of Pushables that way.
There’s quite a lot of flexibility available to you depending on your business requirements, and when non-entities such as interfaces, embeddables, mapped-superclass look like they need to be part of relationships, thinking about promoting or masaging these to entities might also help.
For example change BasicEntity to an entity form a MappedSuperclass – you would need to define your inheritance strategy though – and you can then have a relationship between Account and BasicEntity.
Another option which – and I haven’t tried this - is to define and Abstract entity class that extends BasicEntity and is a super to Package and Service. The class can then be a convenient target for the Many-to-Many from Account, again you would need to think about you inheritance strategy. .
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With