Hibernation mapping for a situation where the key is also used as a many-to-one parameter

I was wondering if there is a way to do a Hibernate mapping for the following. My two days spent on this say no.

There are two tables related to one to many .

 +---------------------+ +-----------------+ | versioned_entity | | basic_entity | +---------------------+ +-----------------+ | fk_BasicEntityId | * 1 | id | | version |-------| active_version | | ... | | ... | +---------------------+ +-----------------+ 

Sleep Mode Display:

 <class name="my.VersionedEntity" table="versioned_entity"> <composite-id> <key-many-to-one name="basicEntity" column="fk_BasicEntityId"/> <key-property name="version"/> </composite-id> ... </class> <class name="my.BasicEntity" table="basic_entity"> <id name="id"> <property name="activeVersion" not-null="true"> <column name="active_version"/> </property> ... </class> 

Short explanation: fk_BasicEntityId is a foreign key pointing to basic_entity.id . An entry in versioned_entity can be identified by its foreign key and version (there can be many versions with the same fk_BasicEntityId ). active_version is a number that points to one of the versioned_entity entries and tells which version is "active". Hope this is clear enough.

Now the problem I am solving is that I need quick access to Java:

 my.BasicEntity basic = my.BasicEntityDAO.get(); my.VersionedEntity activeVersion = basic.getActiveVersionedEntity(); 

The current implementation is performed in Java and simply iterates over all versioned objects of this base object and checks if its version matches the active one. Needless to say, this does not scale and does not lead to performance problems.

So, I went to the database level. Does it look simple? So I thought! I continued and added the following to Hibernate-mapping basic_entity:

 <many-to-one name="activeVersionedEntity" not-null="false" insert="false" update="false"> <column name="id" unique="true" not-null="true"/> <column name="activeVersion"/> </many-to-one> 

This requires a double column for versioned_entity have a composite key. Unfortunately, this will not work - the JVM dies without a trace when the call to be.getActiveVersionedEntity() is called (on the colleague's computer, it throws a StackOverflowError inside Hibernate). I suspect this is happening because "id" is also an identifier, since I have a very similar mapping for the same class where the column is not an identifier, and this works correctly.

Maybe I could do it using HQL, but it would require me to move this method to the DAO class, which is especially inconvenient, since it will require changes to the API (not an option). Using the DAO call inside my.BasicEntity::getActiveVersionedEntity() is another big no-no: I can't mix different levels of abstraction. Another way to resolve this issue would be to search for Interceptors / events, but this is probably also one of those options that pursue the purpose of the structure (I don't need to take care of such low-level things like me?).

I am running Hibernate version: 3.2.7GA / Spring 2.5.6. The documentation is incredibly poor - I looked at three different Hibernate books, online documentation, forums, etc.

Any help is appreciated.

+4
source share
3 answers

Why do you map active_version as a property? I suspect this is an integer, right? Why don't you change active_version to the VersionedEntity type? Thus, it will be a simple one-to-one relationship.

Update:

We use this mapping for one of our sites:

 <many-to-one class="my.VersionedEntity" name="currentVersion" lazy="false" /> 
+1
source

It looks like you are trying to display a specific column twice. I did not understand your problem in detail, but have you considered using update = false and insert = false on one of the mappings? This should allow you to double-match the same column as the relation, and just an integer. More details here .

0
source

Are you modeling a bidirectional reference relationship or inheritance hierarchy?

If the object model is an inheritance hierarchy, then the relationship should not be bidirectional, and the solution is to get an instance of the subclass from the DAO subclass. This eliminates the need to move from a base class to a subclass in a DAO base class. This is what I tried to explain in my original answer (see below).

If the object model is a bi-directional relation, you need to set inverse = "true" in the set or bag at the "one" end of the relation - in this case, BasicEntity.

Hibernate 3 allows you to use indexed collections at the "one" end of the relationship, but the functionality of Hibernate 2 with a kit or bag should be sufficient to test the theory.

This link may help: https://www.hibernate.org/193.html Also: Hibernate Quickly pp142 - 145; Sleep mode in action pp108 - 111.


If I understand the problem correctly, you want to build a VersionedEntity from two tables using the data obtained as follows:

 select * from basic_entity be, versioned_entity ve where ve.id = be.id and ve.id = <id> and ve.active_version=<version> 

Given your limitations on not calling one DAO from another, the question arises as to whether the selected method correctly expresses the intention:

 public my.VersionedEntity my.BasicEntityDAO.getActiveVersionedEntity(); 

Could you implement such a method:

 public my.VersionedEntity my.VersionedEntityDAO.getActive(); 
0
source

All Articles