Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Eclipse Projects » EclipseLink » eclipseLink inheritance joined and oneToMany
eclipseLink inheritance joined and oneToMany [message #1028502] Thu, 28 March 2013 06:40 Go to next message
tex wilco is currently offline tex wilco
Messages: 5
Registered: March 2013
Junior Member
I'm new to eclipseLink and need help to map java classes to an Oracle DB.
I have a catalog of different kind of items (in this case FOLDER and ROOT), each item has its properties that may change during the time so i have to store them with a valid_from and a valid_to dates. For example the FOLDER item is of type 'FOLDER' and has a set of properties named 'FolderData':

@Entity
@Table (name="DIRECTORY_ITEM")
@Access(AccessType.FIELD)
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name="ITEM_TYPE", discriminatorType=DiscriminatorType.STRING, length=100)
public abstract class AbstractItem<T extends AbstractItemData> {

  @Transient
  private transient Class<T> itemDataClass;

  @Id
  private Long id;

  //discriminator field
  @Column(name="ITEM_TYPE", length=100, nullable=false, updatable=false, insertable=false) 
  private String itemType;

  @OneToMany(
      fetch=FetchType.LAZY, 
      mappedBy="item",
      cascade=CascadeType.ALL)
  private Set<T> itemDataSet;

  public AbstractItem(Class<T> itemDataClass) {
    this.itemDataClass = itemDataClass;
  }

    other fields...

    getter and setter....
}

@Entity
@DiscriminatorValue("FOLDER")
public class Folder extends AbstractItem<FolderData> {

  public Folder() {
    super(FolderData.class);
  }
}


@Entity
@DiscriminatorValue("ROOT")
public class Root extends AbstractItem<RootData> {

  public Root() {
    super(RootData.class);
  }
}


The class AbstractItemData is the superclass of FolderData and RootData and I mapped them in the following way:
@Entity
@Table(name="ITEM_DATA_INDEX")
@Access(AccessType.FIELD)
@Inheritance(strategy=InheritanceType.JOINED)
@Configurable
public abstract class AbstractItemData {

    @Id   
  private Long id;

    @ManyToOne(fetch = FetchType.EAGER)
  @JoinColumn(name = "FK_ITEM_ID", nullable = false, insertable=true, updatable=false)
  private AbstractItem<? extends AbstractItemData> item;

  @Column(name="VALID_FROM", nullable=false, columnDefinition = "TIMESTAMP")
  private Date validFrom;

    @Column(name="VALID_TO", nullable=false, columnDefinition = "TIMESTAMP")
  private Date validTo;

    others fields....
    getters and setters...
}

@Entity
@Table(name="ITEM_FOLDER")
@PrimaryKeyJoinColumn(name="ITEM_DATA_ID")
public class FolderData extends AbstractItemData {

  @Column(name="LABEL", length=400, nullable=false)
  private String label;

    others fields....
    getters and setters...
}

@Entity
@Table(name="ITEM_ROOT")
@PrimaryKeyJoinColumn(name="ITEM_DATA_ID")
public class RootData extends AbstractItemData{

  @Column(name="LABEL1", length=400, nullable=false)
  private String label1;

    others fields....
    getters and setters...
}

The problem: EclipseLink requires a discriminator column for joined-relationship but in my case the discriminator is in AbstractItem class (connected by @OneToMany relantionship with AbstractItemData). I tried to use a DescriptorCustomizer and a ClassExtractor declared in the AbstractItemData class but without success. Any suggestions??

thanks.

I'm using eclipseLink 2.4.1 with static weaving.
Re: eclipseLink inheritance joined and oneToMany [message #1031871 is a reply to message #1028502] Tue, 02 April 2013 06:04 Go to previous messageGo to next message
Claude Bernard Diesse is currently offline Claude Bernard Diesse
Messages: 9
Registered: December 2011
Junior Member
1. add ITEM_TYPE Column in ITEM_DATA_INDEX table
2. use it as discriminator column for the AbstractItemData, FolderData, RootData inheritance

hope it helps ...
Re: eclipseLink inheritance joined and oneToMany [message #1034404 is a reply to message #1031871] Fri, 05 April 2013 07:52 Go to previous messageGo to next message
tex wilco is currently offline tex wilco
Messages: 5
Registered: March 2013
Junior Member
Thanks for the help, but I already have the ITEM_TYPE field in table ITEM_DIRECTORY and I don't like to have it also in table ITEM_DATA_INDEX. I'll try to solve in another way.

I don't know if it is a bug or my fault but I tried to add a ClassExtractor implementation to the class AbstractItemData (using @ClassExtractor annotation) and the method 'extractClassFromRow' is never called.
Moreover if I add an implementation of DescriptorCustomizer (using @customizer annotation) with the method 'customize' that is empty the discriminator is no more required.

In this way everything seem to work (insert and update) but when i try to load the lazy oneToMany relationship sometime the generated sql is wrong: it seems eclipseLink is not able to resolve the right table of the class used as generic (e.g. FolderData or RootData).

Maybe using the generics in oneToMany relationship where the generic class uses inheritance is not supported by EclipseLink?

thanks.
Re: eclipseLink inheritance joined and oneToMany [message #1034677 is a reply to message #1034404] Fri, 05 April 2013 15:08 Go to previous messageGo to next message
Chris Delahunt is currently offline Chris Delahunt
Messages: 1018
Registered: July 2009
Senior Member
Can you show the extractor class you are using, as well as the SQL that is generated from a simple "SELECT a from AbstractItemData a"?
Re: eclipseLink inheritance joined and oneToMany [message #1035097 is a reply to message #1034677] Sat, 06 April 2013 06:09 Go to previous messageGo to next message
tex wilco is currently offline tex wilco
Messages: 5
Registered: March 2013
Junior Member
Sorry my fault: in the initialize method of the extractor class i used descriptor.getInheritancePolicy().dontReadSubclassesOnQueries() so EclipseLink (correctly) never call the extractClassFromRow method.

This is the sql 'with' dontReadSubclassesOnQueries():
SELECT ITEM_DATA_ID, CREATED_BY, CREATED_DATE, LAST_MODIFIED_BY, LAST_MODIFIED_DATE, 
       VALID_FROM, VALID_TO, FK_ITEM_ID 
  FROM ITEM_DATA_INDEX   


this is the sql 'without' dontReadSubclassesOnQueries():
SELECT t0.ITEM_DATA_ID, t0.CREATED_BY, t0.CREATED_DATE, t0.LAST_MODIFIED_BY, 
       t0.LAST_MODIFIED_DATE, t0.VALID_FROM, t0.VALID_TO, t0.FK_ITEM_ID, 
       t1.ITEM_DATA_ID, t1.LABEL 
  FROM ITEM_DATA_INDEX t0, ITEM_FOLDER t1 
 WHERE (t1.ITEM_DATA_ID = t0.ITEM_DATA_ID)

SELECT t0.ITEM_DATA_ID, t0.CREATED_BY, t0.CREATED_DATE, t0.LAST_MODIFIED_BY, 
       t0.LAST_MODIFIED_DATE, t0.VALID_FROM, t0.VALID_TO, t0.FK_ITEM_ID, 
       t1.ITEM_DATA_ID, t1.LABEL1 
  FROM ITEM_DATA_INDEX t0, ITEM_ROOT t1 
 WHERE (t1.ITEM_DATA_ID = t0.ITEM_DATA_ID)


But I don't understand why with the following code EclipseLink generate the wrong sql:
      // Search folder with code '|132497614638538'");
      Folder folder = new Folder("|132497614638538");
      folder = repository.load(folder);
      
      // generated sql:
      //      SELECT ITEM_ID, ITEM_TYPE, CREATED_BY, CREATED_DATE, ITEM_CODE,
      //             LAST_MODIFIED_BY, LAST_MODIFIED_DATE 
      //        FROM DIRECTORY_ITEM 
      //        WHERE ((ITEM_TYPE = ?) AND (ITEM_CODE = ?))
      // bind => [FOLDER, |132497614638538]

      // the Folder class is loaded correctly


      if(folder != null) {
        Set<FolderData> folderDataSet = folder.getAllData();  // get lazy data
        
        // generated sql:
        // SELECT t0.ITEM_DATA_ID, t0.CREATED_BY, t0.CREATED_DATE, t0.LAST_MODIFIED_BY,
        //        t0.LAST_MODIFIED_DATE, t0.VALID_FROM, t0.VALID_TO, t0.FK_ITEM_ID,
        //        t1.ITEM_DATA_ID, t1.LABEL1 
        //   FROM ITEM_DATA_INDEX t0, ITEM_ROOT t1 
        //  WHERE ((t0.FK_ITEM_ID = ?) AND (t1.ITEM_DATA_ID = t0.ITEM_DATA_ID))
	// bind => [170]

        // the join should be between ITEM_DATA_INDEX and ITEM_FOLDER and not between 
        // ITEM_DATA_INDEX and ITEM_ROOT

        System.out.println("folderData found: " + folderDataSet.size()); // output: 0
        
      }


I really don't understand where is the mistake!!!
Anyway, at least one little step is made, thank you.

Re: eclipseLink inheritance joined and oneToMany [message #1057913 is a reply to message #1035097] Thu, 09 May 2013 14:27 Go to previous messageGo to next message
tex wilco is currently offline tex wilco
Messages: 5
Registered: March 2013
Junior Member
Finally i had time to debug the eclipseLink metadata generation of the code in the first post and i think there is a bug when it discovers the target classes of the one-to-many relationship declared using generics (in an inheritance scenario).
The only workaround i found is to force the target class in the one-to-many annotation but it is pretty inefficient because it has to do several joins.





Re: eclipseLink inheritance joined and oneToMany [message #1057993 is a reply to message #1057913] Fri, 10 May 2013 07:29 Go to previous message
tex wilco is currently offline tex wilco
Messages: 5
Registered: March 2013
Junior Member
maybe the problem is same?
http://www.eclipse.org/forums/index.php/t/464356/
Previous Topic:create_or_extend_Tables ddl generation issue
Next Topic:I need to capture database warnings, which log level to use?
Goto Forum:
  


Current Time: Sat Aug 30 06:26:00 EDT 2014

Powered by FUDForum. Page generated in 0.01868 seconds