Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Eclipse Projects » EclipseLink » Auto generated Id - Optional late binding mechanism (For clean multi-inheritance JPA code, Id field is declared in shared generic MappedSuperClass, but some derived entities may need to use auto generated value as late overriding mechanism. )
icon4.gif  Auto generated Id - Optional late binding mechanism [message #771202] Mon, 26 December 2011 11:34
Claude Bernard Diesse is currently offline Claude Bernard Diesse
Messages: 9
Registered: December 2011
Junior Member
There is actually a specification gap between JPA and Java 5+ with generics, which prevent us to align entities model to java objects and write clean java code. IMHO, The main reason is the limited capability offered by JPA override mechanisms.

Without a late binding mechanism specifically for Id's, the entities inheritance lake the capacity to adhere properly to Java inheritance scheme using generics. We actually duplicate code to follow relational table design, instead of using generic MappedSuperClass to regroup similar data functions provided for different entity tables, which is not a clean way in java coding.

A simple example follow :
BaseEntity<K> : as mapped super class to define common properties, and a generic primary key K to be defined by derived entities
LongBasedEntity : as derived entity class on LONG_ENTITY table with an auto generate integer prim key
StringBasedEntity : as derived entity class on STRING_ENTITY table with a string prim key
Other derived entities can be added to the inheritance tree, using actual or others tables and different prim key types.

Actually, this example below have the id property commented, and try to use @AttributeOverride to add auto generate capability to the LongBasedEntity derived entities. But this capability is laking in the specs.

@MappedSuperclass  public  abstract class BaseEntity<K extends Serializable> implements Serializable
{
  private static final long serialVersionUID = 1L;
  @Version @Column(name = "VERSION") protected Long version;
  @Id  @Basic(optional = false) @Column(name = "ID", nullable = false) protected K id;

  protected BaseEntity() { super(); }
  protected BaseEntity(K xid) { this.id = xid; }
  public K getId()  {  throw new UnsupportedOperationException("This method must be overrided !"); }
  public void setId(K xid)  {  throw new UnsupportedOperationException("This method must be overrided !"); }
}

@Entity @Table(name = "LONG_ENTITY")
@TableGenerator(name="METAINFO_GEN", table="KBAS_SEQUENCE_TABLE", pkColumnName="SEQ_NAME",  valueColumnName="SEQ_COUNT", pkColumnValue="METAINFO") 
[color=red]@AttributeOverride(name="id", column=@Column(name="ID", updatable=false), [b]generator=@GeneratedValue(strategy=GenerationType.TABLE, generator="METAINFO_GEN"))[/b][/color]
@Inheritance(strategy = InheritanceType.SINGLE_TABLE) @DiscriminatorColumn(name = "ENT_TYPE", discriminatorType = DiscriminatorType.STRING, length=32)
public abstract class LongBasedEntity  extends BaseEntity<Long>
{
  private static final long serialVersionUID = 1L;
  @Basic(optional = false)  @Column(name = "ENT_TYPE", length = 32)  private String entType;

//  @Id @GeneratedValue(strategy=GenerationType.TABLE, generator="METAINFO_GEN") @Column(name="ID",  nullable = false, updatable = false)  private Long id;
 
  protected LongBasedEntity() { super(); }
  protected LongBasedEntity(Long id)  { super(id); }

  public String getEntityType()  { return entType; }
  public void setEntityType(String s)  { this.entType = s; }

}

@Entity @Table(name = "STRING_ENTITY")
@AttributeOverride(name="id", column=@Column(name="ID", length = 64, updatable=false, insertable=false))
@Inheritance(strategy = InheritanceType.SINGLE_TABLE) @DiscriminatorColumn(name = "ENT_TYPE", discriminatorType = DiscriminatorType.STRING, length=32)
public abstract class StringBasedEntity  extends ManagedEntity<String>
{
  private static final long serialVersionUID = 1L;
  @Basic(optional = false)  @Column(name = "ENT_TYPE", length = 32)  private String entType;
//  @Id  @Basic(optional = false) @Column(name = "ID", nullable = false) protected String id;

  protected StringBasedEntity() { super(); }
  protected StringBasedEntity(Long id)  { super(id); }

  public String getEntityType()  { return entType; }
  public void setEntityType(String s)  { this.entType = s; }

}



Is there actually a way to achieve this using EclipseLink, without code duplication and preserving generics meta programming style ?

Because the entity inheritance is greatly based on shared id between derived entities and mapped super class, it is obvious that late binding of the id characteristics is necessary, to achieve clean orm design.

If there is not an actual solution for this, can we ask for an enhancement in EclipseLink ?

This could be to add a generator attribute in the @AttributeOverride annotation, and so give the optional possibility to modify the prim key generation strategy for a particular table.

Thanks for any thoughts and sharing.

regards.



Previous Topic:Catalog &quot;SA&quot; cannot be resolved for table xxxx
Next Topic:java.lang.LinkageError: loader (instance of sun/misc/Launcher$AppClassLoader): attempted duplicate
Goto Forum:
  


Current Time: Fri Aug 22 21:40:43 EDT 2014

Powered by FUDForum. Page generated in 0.07539 seconds