Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
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 Go to next message
Claude Bernard Diesse is currently offline Claude Bernard DiesseFriend
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 Go to previous messageGo to next message
Claude Bernard Diesse is currently offline Claude Bernard DiesseFriend
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 Go to previous messageGo to next message
Claude Bernard Diesse is currently offline Claude Bernard DiesseFriend
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 #772411 is a reply to message #771959] Thu, 29 December 2011 18:04 Go to previous messageGo to next message
Claude Bernard Diesse is currently offline Claude Bernard DiesseFriend
Messages: 9
Registered: December 2011
Junior Member
an enhancement request have been filled in Bugzilla with id=367630

Thanks to vote for that request.

Regards.
Re: Auto generated Id - Optional late binding mechanism [message #772412 is a reply to message #771959] Thu, 29 December 2011 18:04 Go to previous messageGo to next message
Claude Bernard Diesse is currently offline Claude Bernard DiesseFriend
Messages: 7
Registered: July 2009
Junior Member
an enhancement request have been filled in Bugzilla with id=367630

Thanks to vote for that request.

Regards.
Re: Auto generated Id - Optional late binding mechanism [message #777510 is a reply to message #772411] Tue, 10 January 2012 16:09 Go to previous messageGo to next message
James Sutherland is currently offline James SutherlandFriend
Messages: 1939
Registered: July 2009
Location: Ottawa, Canada
Senior Member

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
Re: Auto generated Id - Optional late binding mechanism [message #777514 is a reply to message #772411] Tue, 10 January 2012 16:09 Go to previous messageGo to next message
James Sutherland is currently offline James SutherlandFriend
Messages: 1939
Registered: July 2009
Location: Ottawa, Canada
Senior Member

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 : http://wiki.eclipse.org/EclipseLink : http://en.wikibooks.org/wiki/Java_Persistence : http://java-persistence-performance.blogspot.com/


James : Wiki : Book : Blog : Twitter
Re: Auto generated Id - Optional late binding mechanism [message #779969 is a reply to message #777514] Mon, 16 January 2012 22:59 Go to previous message
Claude Bernard Diesse is currently offline Claude Bernard DiesseFriend
Messages: 9
Registered: December 2011
Junior Member
Hi James,

Thanks for your suggestion ... I will give a look to the DescriptorCustomizer and see if it can solve my needs.

Regards,
Re: Auto generated Id - Optional late binding mechanism [message #779970 is a reply to message #777510] Mon, 16 January 2012 22:59 Go to previous message
Claude Bernard Diesse is currently offline Claude Bernard DiesseFriend
Messages: 7
Registered: July 2009
Junior Member
Hi James,

Thanks for your suggestion ... I will give a look to the DescriptorCustomizer and see if it can solve my needs.

Regards,
Previous Topic:EclipseLink enhancement request in bugzilla
Next Topic:criteria builder missing a condition
Goto Forum:
  


Current Time: Sun Nov 23 08:56:44 GMT 2014

Powered by FUDForum. Page generated in 0.03618 seconds
.:: Contact :: Home ::.

Powered by: FUDforum 3.0.2.
Copyright ©2001-2010 FUDforum Bulletin Board Software