Hi all,
I am having some problems designing the model to represent an existing legacy database schema. I've been referring to the documentation, and while it has lots of individual bits of information that are relevant and helpful I can't figure out how to combine them into the overall picture of what I need. The schema is broadly hierarchical, and each entity has a (potentially) composite primary key, consisting of the "parent" ID and any unique identifiers for the entity itself.
Even at the top level however I am running into problems. The schema for the section I am interested in looks like this:
Code:
ROOT_ENTITY fkey ENTITY_ACCESS_DETAILS
entity_pkey <-----------> entity_pkey
*other non-key columns* *other non-key columns*
/\
/ \
/ \
other child tables
The way the model will be used in the code (and additionally how it conceptually works), I need a link from the RootEntity to the EntityAccessDetails. However, since the AccessDetails doesn't have its own pkey but inherits the key of the Root, we need the relationship mapped in that direction as well.
I have not yet been able to come up with a model that works for both persistence and querying. The closest I have come so far is the following:
Code:
@Entity
@Table(name = "ROOT_ENTITY")
public class RootEntity {
@Id @GeneratedValue(/*generated by sequence, details removed*/)
Integer entity_pkey;
@OneToOne
@PrimaryKeyJoinColumn
AccessDetails accessDetails;
// Other bits
}
--
@Entity
@Table(name = "ENTITY_ACCESS_DETAILS")
public class AccessDetails {
@EmbeddedId
ADKey pkey;
// Other bits
}
@Embeddable
class ADKey implements Serializable {
@OneToOne
@JoinColumn("entity_pkey")
RootEntity entity;
}
This works great during persistence; I can create a RootEntity, then create an associate an AccessDetails object, and when I call save() on the RootEntity both tables are populated correctly (both with the same autogenerated ID). However, when I load the root entity with a query ("from RootEntity e where e.active='Y' and e.entityName=?"), the access details field is always null (not even a proxy). If I force non-lazy loading ("from RootEntity e left join fetch e.accessDetails where e.active='Y' and e.entityName=?"), then a StackOverflowException is the result.
I understood from this last outcome that both entities are trying to load each other, and that I need to make one side the "owner" of the relationship. This would need to be the RootEntity, as that's the class that's generating the ID and propagating it out to the other classes. However, if I modify my ADKey class' annotation to read @OneToOne(mappedBy = "accessDetails"), the session factory will not even load: "org.hibernate.AnnotationException: com.package.ADKey has no persistent id property".
At this point I give up trying to work things out solely through following the documentation (which, by the way, I have been). It seems like my situation is not
that outrageous; what would be the canonical way to map it and make both persistence and loading work?
Many thanks in advance.