Matt Watson created CAY-2667:
--------------------------------
Summary: Fix Wrong ObjEntity with Generic Vertical Inheritance
Key: CAY-2667
URL: https://issues.apache.org/jira/browse/CAY-2667
Project: Cayenne
Issue Type: Bug
Components: Core Library
Reporter: Matt Watson
When using Generic Classes (Java),
with the following db entities:
{code:xml}
<db-entity name="student" schema="poly">
<db-attribute name="name" type="VARCHAR" isMandatory="true"
length="50"/>
<db-attribute name="reference" type="VARCHAR"
isMandatory="true" length="10"/>
<db-attribute name="type" type="CHAR" isMandatory="true"
length="1"/>
<db-attribute name="uuid" type="BINARY" isPrimaryKey="true"
isMandatory="true" length="16"/>
</db-entity>
<db-entity name="boy" schema="poly">
<db-attribute name="toy_trucks" type="SMALLINT" length="4"/>
<db-attribute name="uuid" type="BINARY" isPrimaryKey="true"
isMandatory="true" length="16"/>
</db-entity>
<db-entity name="girl" schema="poly">
<db-attribute name="toy_dolls" type="SMALLINT" length="4"/>
<db-attribute name="uuid" type="BINARY" isPrimaryKey="true"
isMandatory="true" length="16"/>
</db-entity>
{code}
and the following obj entities:
{code:xml}
<obj-entity name="Student" abstract="true" dbEntityName="student">
<obj-attribute name="name" type="java.lang.String"
db-attribute-path="name"/>
<obj-attribute name="reference" type="java.lang.String"
db-attribute-path="reference"/>
<obj-attribute name="type" type="java.lang.String"
db-attribute-path="type"/>
</obj-entity>
<obj-entity name="Boy" superEntityName="Student">
<qualifier><![CDATA[type = "B"]]></qualifier>
<obj-attribute name="toyTrucks" type="java.lang.Short"
db-attribute-path="boy.toy_trucks"/>
</obj-entity>
<obj-entity name="Girl" superEntityName="Student">
<qualifier><![CDATA[type = "G"]]></qualifier>
<obj-attribute name="toyDolls" type="java.lang.Short"
db-attribute-path="girl.toy_dolls"/>
</obj-entity>
{code}
and proper db/obj relationships setup ..
using the Test:
{code:java}
final DataContext dataContext = (DataContext) runtime.newContext();
final DataObject girlEmma = (DataObject) dataContext.newObject("Girl");
girlEmma.writeProperty("reference", "g1");
girlEmma.writeProperty("name", "Emma");
girlEmma.writeProperty("toyDolls", 5);
final DataObject boyLuke = (DataObject) dataContext.newObject("Boy");
boyLuke.writeProperty("reference", "b1");
boyLuke.writeProperty("name", "Luke");
boyLuke.writeProperty("toyTrucks", 12);
dataContext.commitChanges();
{code}
{noformat}
15:43:22.418 [main] INFO org.apache.cayenne.log.JdbcEventLogger - ---
transaction started.
15:43:22.420 [main] INFO org.apache.cayenne.log.JdbcEventLogger - INSERT INTO
poly.student (name, reference, type, uuid) VALUES (?, ?, ?, ?)
15:43:22.429 [main] INFO org.apache.cayenne.log.JdbcEventLogger - [bind:
1->name:'Emma', 2->reference:'g1', 3->type:'G',
4->uuid:3fed46ae-a9d6-45c7-a306-402a0710e5a1]
15:43:22.435 [main] INFO org.apache.cayenne.log.JdbcEventLogger - === updated
1 row.
15:43:22.437 [main] INFO org.apache.cayenne.log.JdbcEventLogger - [bind:
1->name:'Luke', 2->reference:'b1', 3->type:'G',
4->uuid:f113e95a-8727-414d-8ed4-ed08ba80c48b]
15:43:22.443 [main] INFO org.apache.cayenne.log.JdbcEventLogger - === updated
1 row.
15:43:22.445 [main] INFO org.apache.cayenne.log.JdbcEventLogger - INSERT INTO
poly.girl (toy_dolls, uuid) VALUES (?, ?)
15:43:22.450 [main] INFO org.apache.cayenne.log.JdbcEventLogger - [bind:
1->toy_dolls:5, 2->uuid:3fed46ae-a9d6-45c7-a306-402a0710e5a1]
15:43:22.454 [main] INFO org.apache.cayenne.log.JdbcEventLogger - === updated
1 row.
15:43:22.455 [main] INFO org.apache.cayenne.log.JdbcEventLogger - INSERT INTO
poly.boy (toy_trucks, uuid) VALUES (?, ?)
15:43:22.460 [main] INFO org.apache.cayenne.log.JdbcEventLogger - [bind:
1->toy_trucks:12, 2->uuid:f113e95a-8727-414d-8ed4-ed08ba80c48b]
15:43:22.464 [main] INFO org.apache.cayenne.log.JdbcEventLogger - === updated
1 row.
15:43:22.487 [main] INFO org.apache.cayenne.log.JdbcEventLogger - +++
transaction committed.
{noformat}
It inserts 2 records into [student], 1 record into [boy], 1 record into [boy],
but the [type] on both student records is "G", instead of one "B" and one "G".
Its doing this because of a bug during BaseContext.injectInitialValue when
creating the Boy ... the line:
getEntityResolver().getObjEntity(object.getClass()) its returning the "Girl"
ObjEntity
the MappingCache.objEntitiesByClassName holds an entry for "CayenneDataObject"
with value for Girl ObjEntity. When using Generics there will be many
ObjEntities that use CayenneDataObject, so we shouldn't be asking for it from
this cache Map.
we should use: getEntityResolver().getObjEntity((Persistent)object) because
that one is properly getting the correct ObjEntity from the ObjectId, in
MappingCache.getObjEntity(Persistent object)
I can work on a breaking test, and potential fix
--
This message was sent by Atlassian Jira
(v8.3.4#803005)