Home » Eclipse Projects » EclipseLink » eclipseLink inheritance joined and oneToMany
eclipseLink inheritance joined and oneToMany [message #1028502] |
Thu, 28 March 2013 10:40 |
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 #1035097 is a reply to message #1034677] |
Sat, 06 April 2013 10:09 |
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.
|
|
| | |
Goto Forum:
Current Time: Thu Apr 18 09:18:48 GMT 2024
Powered by FUDForum. Page generated in 0.02727 seconds
|