datanucleus / datanucleus-rdbms

DataNucleus support for persistence to RDBMS Datastores
30 stars 66 forks source link

Relation to Object and interface using entity name column and id column #429

Open spassignat opened 2 years ago

spassignat commented 2 years ago

Hello,

If you have a relation from a class to an interface, it would be great to have a two column mapping with one for the entity name (or discriminator) or the target table name and one (at least) for the identifier of the row in that target table.

@Entity(name="EntityA")
@Table(name="TableA")
public class ClassA{
  @ManyToOne
  @Extension(key="mapping-strategy", value="entity-id")
  private  InterfaceB refB; 
}

@Entity(name="EntityC")
@Table(name="TableC")
public class ClassC implements InterfaceB{
}

@Entity(name="EntityD")
@Table(name="TableD")
public class ClassD implements InterfaceB{
}

public interface InterfaceB{
  @Id
  long getId();
  @Basic 
  String getName();
}
TableA id refB_type refB_Id
1 EntityC 12
2 EntityD 23
TableC id ...
12 ...
TableD id ...
23 ...

SQL aspects

Fetching graphs including such relationships might be intensive on the database and depends of the model complexity (inheritance, relationship cardinality, ... but this model also allows to fetch graphs like per-implementation and allows to keep the table model unchanged when a new interface implementation is added.

SELECT * FROM TableA a JOIN TableC c on a.refB_Id=c.id and refB_type='EntityC'
UNION
SELECT * FROM TableA a JOIN TableD c on a.refB_Id=c.id and refB_type='EntityD'

Query aspects

Querying through the links would be great if JPA would support casting but querying on getter/setter methods declared on the interface can also be a first step.

entityManager.createQuery("select e from EntityA e where e.refB.name like :param, ClassA.class)
andyjefferson commented 2 years ago

Anybody can get the code and contribute such things. We already provide 2 such mapping strategies, multiple FKs, or single String which includes the class + id.