Home » Eclipse Projects » EclipseLink » Auto generated Id - Optional late binding mechanism
Auto generated Id - Optional late binding mechanism [message #771203] |
Mon, 26 December 2011 16:34 |
Claude Bernard Diesse Messages: 7 Registered: July 2009 |
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")
@AttributeOverride(name="id", column=@Column(name="ID", updatable=false), generator=@GeneratedValue(strategy=GenerationType.TABLE, generator="METAINFO_GEN"))
@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.
|
|
|
Re: Auto generated Id - Optional late binding mechanism [message #771959 is a reply to message #771203] |
Wed, 28 December 2011 16:38 |
Claude Bernard Diesse Messages: 9 Registered: December 2011 |
Junior Member |
|
|
I intend to ask for enhancement in EclipseLink @OverrideAttribute annotation.
But need to check if someone out there have another solution ... My java projects use generics more often, but java code related to JPA based models, are clumsy and uneasy verbose. I will like to know if others java coders are experiencing the same constraints.
I have found on the Web, some people asking a way to override the generator strategy in derived classes.
By the way, this seem to be something affordable, because the attribute binding is done at the entity level and not at the Mapped super class level.
As the example below can show, the generator strategy and the AttributeOverride can be defined at the class level.
JPA interface redefinition :
@Target({TYPE, METHOD, FIELD}) @Retention(RUNTIME)
public @interface AttributeOverride {
String name();
Column column();
GeneratedValue generator();
}
example :
@Entity @Table(name = "LONG_ENTITY")
@TableGenerator(name="METAINFO_GEN", table="KBAS_SEQUENCE_TABLE", pkColumnName="SEQ_NAME", valueColumnName="SEQ_COUNT", pkColumnValue="METAINFO")
@AttributeOverride(name="id", column=@Column(name="ID", updatable=false), generator=@GeneratedValue(strategy=GenerationType.TABLE, generator="METAINFO_GEN"))
AttributeOverride Annotation Elements
Type Name Description Default
===== =========== ======================================= =========
String name (Required) The name of the property whose mapping is being overridden
if property-based access is being used, or the name of the field
if field-based access is used.
Column column (Required) The column that is being mapped to the persistent
attribute. The mapping type will remain the same as is
GeneratedValue generator (Optional) The optional generation strategy defined for the id field.
To be used only for prim key fields.
So if no one object, I will ask for that enhancement and your vote for it.
Thanks.
|
|
|
Re: Auto generated Id - Optional late binding mechanism [message #771960 is a reply to message #771203] |
Wed, 28 December 2011 16:38 |
Claude Bernard Diesse Messages: 7 Registered: July 2009 |
Junior Member |
|
|
I intend to ask for enhancement in EclipseLink @OverrideAttribute annotation.
But need to check if someone out there have another solution ... My java projects use generics more often, but java code related to JPA based models, are clumsy and uneasy verbose. I will like to know if others java coders are experiencing the same constraints.
I have found on the Web, some people asking a way to override the generator strategy in derived classes.
By the way, this seem to be something affordable, because the attribute binding is done at the entity level and not at the Mapped super class level.
As the example below can show, the generator strategy and the AttributeOverride can be defined at the class level.
JPA interface redefinition :
@Target({TYPE, METHOD, FIELD}) @Retention(RUNTIME)
public @interface AttributeOverride {
String name();
Column column();
GeneratedValue generator();
}
example :
@Entity @Table(name = "LONG_ENTITY")
@TableGenerator(name="METAINFO_GEN", table="KBAS_SEQUENCE_TABLE", pkColumnName="SEQ_NAME", valueColumnName="SEQ_COUNT", pkColumnValue="METAINFO")
@AttributeOverride(name="id", column=@Column(name="ID", updatable=false), generator=@GeneratedValue(strategy=GenerationType.TABLE, generator="METAINFO_GEN"))
AttributeOverride Annotation Elements
Type Name Description Default
===== =========== ======================================= =========
String name (Required) The name of the property whose mapping is being overridden
if property-based access is being used, or the name of the field
if field-based access is used.
Column column (Required) The column that is being mapped to the persistent
attribute. The mapping type will remain the same as is
GeneratedValue generator (Optional) The optional generation strategy defined for the id field.
To be used only for prim key fields.
So if no one object, I will ask for that enhancement and your vote for it.
Thanks.
|
|
| | |
Re: Auto generated Id - Optional late binding mechanism [message #777510 is a reply to message #772411] |
Tue, 10 January 2012 16:09 |
|
You could probably not map the id in the superclass, and instead map it in the subclasses. This is hard to do with annotation (maybe using property access) but might be possible if you use orm.xml to map the ids (you can use both annotations and xml).
In EclipseLink you could define a DescriptorCustomizer in the subclass and override anything you wish, include the sequenceName or sequenceFieldName.
James : Wiki : Book : Blog : Twitter
|
|
| | | |
Goto Forum:
Current Time: Mon Sep 23 01:25:21 GMT 2024
Powered by FUDForum. Page generated in 0.04406 seconds
|