Skip to main content


Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Modeling » EMF » Teneo: Avoiding unnecessary joins(Avoiding pointless joins to impossible containers when a class is a child of multiple containments)
Teneo: Avoiding unnecessary joins [message #1809108] Tue, 09 July 2019 08:47
Ben Tenne is currently offline Ben TenneFriend
Messages: 50
Registered: October 2009
Member
Hi,

I have three classes, Car, Motorcycle and Engine.

  --------------             --------------
  |    Car     |             | Motorcycle |
  --------------             --------------
             /\                /\
             \/                \/
             |                 |
 engine 0..1 |                 | engine 0..1
           -----------------------
           |       Engine        |
           -----------------------
 


Cars and Motorcycles both have Engines, so each have an EReference ('engine') referring to Engine.

e.g. (in Car)

    <eStructuralFeatures xsi:type="ecore:EReference" name="engine" eType="//Engine" containment="true" resolveProxies="false" eOpposite="//Engine/oppCarengine">
      <eAnnotations source="http:///org/eclipse/emf/ecore/util/ExtendedMetaData">
        <details key="kind" value="element"/>
        <details key="name" value="engine"/>
      </eAnnotations>
      <eAnnotations source="teneo.jpa">
        <details key="value" value="@OneToOne(mappedBy=&quot;oppCarengine&quot;)"/>
      </eAnnotations>
    </eStructuralFeatures>


As you can see, it refers to an opposite feaure ('oppCarengine') in Engine, which looks like this:

    <eStructuralFeatures xsi:type="ecore:EReference" name="oppCarengine" eType="//Car" transient="true" eOpposite="//Car/engine">
      <eAnnotations source="teneo.jpa">
        <details key="value" value="@JoinColumn(name=&quot;CAR_ENGINE_XXXID&quot;)"/>
      </eAnnotations>
    </eStructuralFeatures>


The relevant excerpts from the generated Hibernate mappings look like this:

<class name="CarImpl" ...
...
  <one-to-one name="engine" entity-name="com.example.bdp2.Engine" cascade="all" lazy="false" property-ref="oppCarengine"/>
</class>


<class name="EngineImpl"  ...
...
  <many-to-one name="oppCarengine" entity-name="com.example.bdp2.Car" cascade="merge,persist,save-update,lock,refresh" not-null="false" lazy="false" insert="true" update="true">
    <column not-null="false" unique="false" name="`CAR_ENGINE_XXXID`" index="IDX_1_BDP2_6F6B83114642FBB2F19"/>
  </many-to-one>
 </class>


(I have a similar 'engine' feature on Motorcycle, which has an opposite ('oppMotorcycleengine') on Engine)

The primary reason for having this opposite is because I want the database to have a child-to-parent foreign key; i.e. a column in Engine referring to Car, rather than the other way around.

This works fine, but the problem is that the SQL to fetch a Car is needlessly traversing the reference from Engine to Motorcycle, which is obviously unnecessary, given that a single engine can only be contained within either a Car OR a Motorcycle, but not both, given that they are containment relationships.

i.e.

SELECT this_.[xxx_id]                     AS XXX1_904_2_,
       this_.[xxx_version]                AS XXX3_904_2_,
       this_.[id]                         AS ID4_904_2_,
       engine2_.[xxx_id]                  AS XXX1_905_0_,
       engine2_.[capacity]                AS CAPACITY3_905_0_,
       engine2_.[car_engine_xxxid]        AS CAR5_905_0_,
       engine2_.[motorcycle_engine_xxxid] AS MOTORCYCLE6_905_0_,
       motorcycle3_.[xxx_id]              AS XXX1_906_1_,
       motorcycle3_.[xxx_version]         AS XXX3_906_1_,
       motorcycle3_.[id]                  AS ID4_906_1_
FROM   [car] this_
       LEFT OUTER JOIN [engine] engine2_
                    ON this_.[xxx_id] = engine2_.[car_engine_xxxid]
       LEFT OUTER JOIN [motorcycle] motorcycle3_
                    ON engine2_.[motorcycle_engine_xxxid] =
                       motorcycle3_.[xxx_id]
WHERE  this_.[xxx_id] IN ( ? )  


In reality, what I've shown is a dramatic simplification of my model. There are several other classes also containing Engines, which in turn are part of a bigger model with other patterns of classes like Engine having multiple containers. This is resulting in a crazy number of joins which is hitting performance.

Is there anything I could do in the Ecore to prevent this? If not, can I modify the Hibernate mapping somehow to prevent the pointless traversal up the containment tree?

Many thanks for any advice!

Regards,
Ben.

[Updated on: Thu, 11 July 2019 17:12]

Report message to a moderator

Previous Topic:Wrap a mutable Java type into a Datatype?
Next Topic:Issue when trying to add Custom Date Type
Goto Forum:
  


Current Time: Tue Dec 10 08:13:48 GMT 2019

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

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

Back to the top