[GLASSFISH-399] java2db : Java 2 MySQL 2 type mapping to be updated Created: 14/Mar/06  Updated: 06/Mar/12

Status: Open
Project: glassfish
Component/s: entity-persistence
Affects Version/s: 9.0pe
Fix Version/s: not determined

Type: Improvement Priority: Major
Reporter: bjb Assignee: guruwons
Resolution: Unresolved Votes: 1
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified
Environment:

Operating System: All
Platform: All


Issuezilla Id: 399

 Description   

Taking this as reference :
http://fisheye5.cenqua.com/viewrep/glassfish/entity-persistence/src/java/oracle/toplink/essentials/platform/database/MySQL4Platform.java?r=1.5

For MySQL4 some of the default type mapping has to be updated to fit the default
Java type to the closest MySQL data type (of course, user is free to customize
the type in persistence, but default mapping should not involve "data loss" as
much as possible, at least as long as the database make it possible).

FYI, I've removed the 64000 as there is no reason not to rely on default "65535"
(aka "64k" and loose 1535 byte of storage each time).

Hence the following changes are anticipated :

Instead of :
fieldTypeMapping.put(Boolean.class, new FieldTypeDefinition("TINYINT(1) default
0", false));
put :
fieldTypeMapping.put(Boolean.class, new FieldTypeDefinition("BOOL DEFAULT
FALSE", false));

Instead of:
fieldTypeMapping.put(String.class, new FieldTypeDefinition("VARCHAR", 255));
put VARCHAR is limited to has max length of 255 on pre 5.0 mysql
fieldTypeMapping.put(String.class, new FieldTypeDefinition("TEXT", 255));
(default size of 255 will switch the real type to "TINY TEXT" that is 255 char
max width, personally I would have removed this contraints....)

Instead of :
fieldTypeMapping.put(java.sql.Blob.class, new FieldTypeDefinition("BLOB", 64000));
put :
fieldTypeMapping.put(java.sql.Blob.class, new FieldTypeDefinition("BLOB");
(here this will put 65535 which is the default)

fieldTypeMapping.put(java.sql.Clob.class, new FieldTypeDefinition("TEXT", 64000));
put
fieldTypeMapping.put(java.sql.Clob.class, new FieldTypeDefinition("TEXT"));
(default for TEXT is 65535)

Last thing that needs to be looked deeply is the TIMESTAMP :
fieldTypeMapping.put(java.sql.Timestamp.class, new
FieldTypeDefinition("DATETIME", false));

Precision of DATETIME is not matching java.sql.TimeStamp, so data is lost here
when storing the data to the DBMS. A better type has to be found TIMESTAMP might
be a good candidate but behaviour has to be taken care.



 Comments   
Comment by pramodgo [ 17/Mar/06 ]

Thank for the detailed issue report.
At this point of time I am changing the Issue type to "ENHANCEMENT."

Will have to revisit all the platforms and check these settings for each and
every field type.

Comment by pramodgo [ 17/Mar/06 ]

...

Comment by bjb [ 21/Mar/06 ]

Dear pramodgo,
I think cleaning all the SQL platform is a good idea.

Meanwhile, could it be possible at least to apply on th head the boolean and
string fix suggested ?

This would just save us time

Rgs,
JB

Comment by guruwons [ 12/Mar/07 ]

I'm reviewing the default data types of MySQL platform.

For Boolean, BOOL and BOOLEAN is synonym for TINYINT(1), so there is no need to
change it.

For String, TEXT(255) does not work on MySQL 4.0(4.1 support this).
@Column(length=n) can be used for VARCHAR which is translated into
corresponding TEXT type beginging with MySQL 4.1. Hence, it should be unchanged.

For Blob and Clob, BLOB(64000) and TEXT(64000) is interpreted as BLOB and TEXT.
But I think it should be LONGBLOB and LONGTEXT because the maximum size of
BLOB/TEXT is limited within 65,535 bytes.

For Timestamp, type TIMESTAMP does not support nanoseconds either. There is no
better type now in MySQL.

Comment by Tom Mueller [ 06/Mar/12 ]

Bulk update to change fix version to "not determined" for all issues still open but with a fix version for a released version.





[GLASSFISH-1153] Object can't reference itself using @EmbeddedId Created: 18/Sep/06  Updated: 30/Nov/10

Status: Reopened
Project: glassfish
Component/s: entity-persistence
Affects Version/s: 9.0pe
Fix Version/s: 9.1pe_dev

Type: Bug Priority: Minor
Reporter: keinhaar Assignee: guruwons
Resolution: Unresolved Votes: 2
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified
Environment:

Operating System: Windows XP
Platform: Other


Attachments: Microsoft Word issue1153_fix.diff    
Issuezilla Id: 1,153

 Description   

I have a class hierarchy which uses an embeddedId. NaturalPerson is derived from
Person. NaturalPerson has a List of children where each child is again a
NaturalPerson.
Inheritance is declared as JOINED.

This works fine if Guid is replaced by an String or integer id, but does not
work if the Persons id is an EmbeddedId like Guid. (see error message at the
bottom of this post)

see the forum for a short discussion with more information:
http://forums.java.net/jive/thread.jspa?messageID=154177&#154177

this is a bug, because the id should be found even if it has been declared on
the superclass.

This are the relevant parts of the classes:
@Embeddable class Guid
{
@Id public String getId()

{...}
...
}

@Entity class Person
{
@EmbeddedId public Guid getId(){...}

}

@Entity class NaturalPerson extends Person
{
@ManyToMany(cascade=CascadeType.ALL)
@JoinTable( joinColumns=@JoinColumn(name="parent_id",referencedColumnName="id"),
inverseJoinColumns=@JoinColumn(name="child_id",referencedColumnName="id")
)
public List<NaturalPerson> getChildren()

{...}

}

javax.persistence.RollbackException: Exception [TOPLINK-45] (Oracle TopLink
Essentials - 2006.8 (Build 060829)):
oracle.toplink.essentials.exceptions.DescriptorException
Exception Description: Missing mapping for field [NATURALPERSON.id].
Descriptor: RelationalDescriptor(me.utils.Guid --> [DatabaseTable(PERSON)])



 Comments   
Comment by keinhaar [ 28/Sep/06 ]
      • Issue 1153 has been confirmed by votes. ***
Comment by guruwons [ 13/Oct/06 ]

I'm looking into this.

  • Wonseok Kim
Comment by guruwons [ 13/Oct/06 ]

Started to work on this.

Comment by guruwons [ 13/Oct/06 ]

This exception occurs for all types of relationships whose target is a child
entity which has JOINED inheritance strategy and Embedded Id.

Following are an exception example.
----------
Caused by: Exception [TOPLINK-45] (Oracle TopLink Essentials - 9.1 (Build )):
oracle.toplink.essentials.exceptions.DescriptorException
Exception Description: Missing mapping for field [NATURALPERSON.ID].
Descriptor: RelationalDescriptor(jpatests.model.Guid --> [DatabaseTable(PERSON)])
at
oracle.toplink.essentials.exceptions.DescriptorException.missingMappingForField(DescriptorException.java:885)
at
oracle.toplink.essentials.internal.descriptors.ObjectBuilder.extractValueFromObjectForField(ObjectBuilder.java:1584)
at
oracle.toplink.essentials.mappings.AggregateObjectMapping.valueFromObject(AggregateObjectMapping.java:912)
at
oracle.toplink.essentials.internal.descriptors.ObjectBuilder.extractValueFromObjectForField(ObjectBuilder.java:1587)
at
oracle.toplink.essentials.mappings.OneToOneMapping.writeFromObjectIntoRow(OneToOneMapping.java:1058)
at
oracle.toplink.essentials.internal.descriptors.ObjectBuilder.buildRow(ObjectBuilder.java:732)
at
oracle.toplink.essentials.internal.descriptors.ObjectBuilder.buildRow(ObjectBuilder.java:720)
at
oracle.toplink.essentials.internal.queryframework.DatabaseQueryMechanism.insertObjectForWrite(DatabaseQueryMechanism.java:425)
at
oracle.toplink.essentials.queryframework.InsertObjectQuery.executeCommit(InsertObjectQuery.java:74)
at
oracle.toplink.essentials.internal.queryframework.DatabaseQueryMechanism.performUserDefinedWrite(DatabaseQueryMechanism.java:635)
at
oracle.toplink.essentials.internal.queryframework.DatabaseQueryMechanism.performUserDefinedInsert(DatabaseQueryMechanism.java:599)
at
oracle.toplink.essentials.internal.queryframework.DatabaseQueryMechanism.insertObjectForWriteWithChangeSet(DatabaseQueryMechanism.java:495)
at
oracle.toplink.essentials.queryframework.WriteObjectQuery.executeCommitWithChangeSet(WriteObjectQuery.java:130)
at
oracle.toplink.essentials.internal.queryframework.DatabaseQueryMechanism.executeWriteWithChangeSet(DatabaseQueryMechanism.java:283)
at
oracle.toplink.essentials.queryframework.WriteObjectQuery.executeDatabaseQuery(WriteObjectQuery.java:67)
at
oracle.toplink.essentials.queryframework.DatabaseQuery.execute(DatabaseQuery.java:609)
at
oracle.toplink.essentials.queryframework.DatabaseQuery.executeInUnitOfWork(DatabaseQuery.java:536)
at
oracle.toplink.essentials.queryframework.ObjectLevelModifyQuery.executeInUnitOfWorkObjectLevelModifyQuery(ObjectLevelModifyQuery.java:123)
at
oracle.toplink.essentials.queryframework.ObjectLevelModifyQuery.executeInUnitOfWork(ObjectLevelModifyQuery.java:95)
at
oracle.toplink.essentials.internal.sessions.UnitOfWorkImpl.internalExecuteQuery(UnitOfWorkImpl.java:2218)
at
oracle.toplink.essentials.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:937)
at
oracle.toplink.essentials.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:894)
at
oracle.toplink.essentials.internal.sessions.CommitManager.commitNewObjectsForClassWithChangeSet(CommitManager.java:254)
at
oracle.toplink.essentials.internal.sessions.CommitManager.commitAllObjectsWithChangeSet(CommitManager.java:175)
at
oracle.toplink.essentials.internal.sessions.AbstractSession.writeAllObjectsWithChangeSet(AbstractSession.java:2638)
at
oracle.toplink.essentials.internal.sessions.UnitOfWorkImpl.commitToDatabase(UnitOfWorkImpl.java:1030)
at
oracle.toplink.essentials.internal.ejb.cmp3.base.RepeatableWriteUnitOfWork.commitToDatabase(RepeatableWriteUnitOfWork.java:357)
at
oracle.toplink.essentials.internal.sessions.UnitOfWorkImpl.commitToDatabaseWithChangeSet(UnitOfWorkImpl.java:1112)
at
oracle.toplink.essentials.internal.ejb.cmp3.base.RepeatableWriteUnitOfWork.commitRootUnitOfWork(RepeatableWriteUnitOfWork.java:82)
at
oracle.toplink.essentials.internal.sessions.UnitOfWorkImpl.commitAndResume(UnitOfWorkImpl.java:842)
at
oracle.toplink.essentials.internal.ejb.cmp3.transaction.base.EntityTransactionImpl.commit(EntityTransactionImpl.java:90)
... 26 more
----------

CAUSE

If entity B is a child entity of entity A which has composite primary key by
@EmbeddedId, the internal class descriptor of B inherit mappings from the
descriptor of A. Therefore B has same AggregateObjectMapping instance of entity
A, and the AggregateObjectMapping instance has only fields of entity A. For
example, if the primary key fields of A are A.ID1 and A.ID2 (table 'A'), and the
primary key fields of B are B.ID1 and B.ID2, the AggregateObjectMapping has only
A.ID1 and A.ID2.

If ObjectBuilder.extractValueFromObjectForField() is called to get primary key
value of child entity B with B.ID1, the AggregateObjectMapping doesn't find
corresponding mapping with B.ID1 because it only knows A.ID1 and A.ID2. So an
Exception like belwo is thrown.

[TOPLINK-45] oracle.toplink.essentials.exceptions.DescriptorException
Exception Description: Missing mapping for field [B.ID1].

So we need to call ObjectBuilder.extractValueFromObjectForField() of
AggregateObjectMapping with the field A.ID1 instead of given B.ID1.

I'm working on the fix.

Comment by tware [ 19/Oct/06 ]

Created an attachment (id=530)
diff file for fix

Comment by tware [ 19/Oct/06 ]

Fix by Wonsoek Kim checked in.

Comment by sherryshen [ 07/Nov/06 ]

Verified in 9.1pe_b24.

Comment by Sanjeeb Sahoo [ 14/Nov/06 ]

Wonseok,

You mentioned the following in your comments where you explained the CAUSE of
the bug:
"If entity B is a child entity of entity A ... For example, if the primary key
fields of A are A.ID1 and A.ID2 (table 'A'), and the primary key fields of B are
B.ID1 and B.ID2, the AggregateObjectMapping has only A.ID1 and A.ID2."

I don't understand how B can have separate primary key columns than A when B
extends A. Even when JOINED inheritance strategy is used, won't B have the same
PK columns as A?

– Sahoo

Comment by guruwons [ 15/Nov/06 ]

I meant primary keys in table perspective. B has B.ID1 and B.ID2 columns which
correspond to primary keys columns of A - A.ID1 and A.ID2. They are actually
used as foreign keys to table A for joining. B.ID1 and B.ID2 actually don't need
be primary keys in table B, but they are generated as primary keys by DDL
generation. Also they have a generated foreign key constraint (B.ID1, B.ID2) ->
(A.ID1, A.ID2).
Their mappings are maintained in ClassDescriptor.additionalTablePrimaryKeyFields
member as same as secondary table cases.

Comment by Sanjeeb Sahoo [ 15/Nov/06 ]

Hi Wonseok,

Although Table B has ID1 and ID2 as primary key columns and those two columns
are also foreign keys to A.ID1 and A.ID2, but the IDs for the derived entity B
should still be mapped to A.ID1 and A.ID2. That's my understanding. In the
example below(thanks to Sherry Shen who brought this use case to my attention)
where the columns in derived classes have been renamed to PK1 and PK2
respectively, should the referencedColumnNames in @JoinTable be using PK1 and
PK2 or ID1 and ID2? I think, they should be using ID1 and ID2 as shown below.

@Embeddable class Person

{ String id1; String id2; }

@Entity
@Inheritance(strategy=JOINED)
class Person

{ @EmbeddedId PersonPK personPK; ... }

@Entity
@PrimaryKeyJoinColumns(

{ @PrimaryKeyJoinColumn(name="PK1", referencedColumnName="ID1"), @PrimaryKeyJoinColumn(name="PK2", referencedColumnName="ID2") }

)
public class NaturalPerson {
@ManyToMany(cascade=CascadeType.ALL)
@JoinTable(name="PARENT_CHILDREN",
joinColumns=

{ @JoinColumn(name="P_ID1", referencedColumnName="ID1"), @JoinColumn(name="P_ID2", referencedColumnName="ID2") }

,
inverseJoinColumns=

{ @JoinColumn(name="C_ID1", referencedColumnName="ID1"), @JoinColumn(name="C_ID2", referencedColumnName="ID2") }

)
List<NaturalPerson> children;
}

With the current fix in place, this does not work. It works when we use PK1 and
PK2 as the referenced column names in @JoinTable.

Thanks,
Sahoo

Comment by guruwons [ 16/Nov/06 ]

Interesting,
the issue is not confined to EmbeddedId but applicable to all relationships with
subclasses which has joined inheritance strategy. So I think this is another
issue and need to be discussed in mailing list (probably with spec leads?).

Thanks for bringing this up, Sahoo. I will send another email to mailing list.

Comment by Peter Salomonsen [ 30/Sep/08 ]

This problem still exist in glassfish-v2ur2. We are trying to use JOINED
inheritance strategy, and experience that the SQL generated from TOPLINK creates
two joins to the inherited table, but only references one of the PK columns.

"..... LEFT OUTER JOIN PolygonArea t1 ON (t1.NAME = t0.NAME) LEFT OUTER JOIN
PolygonArea t1 ON (t1.NAME = t0.NAME) ....."

While it rather should have t1.NAME = t0.NAME AND t1.CUSID = t0.CUSID, and not
two equal repeated joins...

Comment by sanandal [ 11/Jan/09 ]

"Reclassifying as P4 because this issue is not deemed "must fix" for this v2.1
release whose primary release driver is SailFin.
This issue will be scrubbed after this release and will be given the right
priority for the next release."





Generated at Sat Mar 28 09:33:24 UTC 2015 using JIRA 6.2.3#6260-sha1:63ef1d6dac3f4f4d7db4c1effd405ba38ccdc558.