hibernate not able to populate the bi-directional relationship collection when fk is not pointing to id

35 Views Asked by At

I have an issue about hibernate. As you can see I have a many to one relationship between EnvelopeEvent and EnvelopeProcess, the thing is I am not using ID to do the link, instead in table ENVELOPE_EVENT.ENVELOPE_FK it is pointing to ENVELOPE_PROCESS.ENVELOPE_ID, everything works perfect when I do insert. But when I try to select, EnvelopeProcess.events is always empty. I turned on the hibernate logs, and I notice it is using EnvelopeProcess.id as the key to lookup EnvelopeEvent, which is not what my purpose. I want it to use EnvelopeProcess.envelopeId to look for EnvelopeEvent. When I do debugging, I also notice org.hibernate.type.CollectionType.foreignKeyPropertyName is always null for my class EnvelopeProcess , which is also not what is supposed to be. My hibernate version is 5.4.27.Final

Here is my code:

public class EnvelopeProcess extends AbstractEntity{

private static final long serialVersionUID = 222222L;

private String envelopeId;

private String status;

private String subject;

private Set<EnvelopeEvent> events;

public Long getQuoteId() {
    return quoteId;
}
public void setQuoteId(Long quoteId) {
    this.quoteId = quoteId;
}
public String getEnvelopeId() {
    return envelopeId;
}
public void setEnvelopeId(String envelopeId) {
    this.envelopeId = envelopeId;
}
public String getStatus() {
    return status;
}
public void setStatus(String status) {
    this.status = status;
}
public String getSubject() {
    return subject;
}
public void setSubject(String subject) {
    this.subject = subject;
}
public Set<EnvelopeEvent> getEvents() {
    return events;
}
public void setEvents(Set<EnvelopeEvent> events) {
    this.events = events;
}
//order by trigger time from latest to oldest
public List<EnvelopeEvent> getOrderedEvents(){
    return this.events.stream()
            .sorted((e1, e2) -> e2.getTriggerTime().compareTo(e1.getTriggerTime()))
            .collect(Collectors.toList());
}

public EnvelopeEvent getLatestEvent() {
    return this.getOrderedEvents().get(0);
}

}
<class name="com.pat.storage.entities.EnvelopeProcess" table="ENVELOPE_PROCESS" polymorphism="implicit" mutable="true" dynamic-insert="false" dynamic-update="false" >
    <cache usage="read-write" region="com.pat.storage.entities"/>
    <id name="id" type="long" unsaved-value="null" >
        <column name="ID"/>
        <generator class="org.hibernate.id.enhanced.SequenceStyleGenerator">
            <param name="sequence_name">ZSEQID_ENVELOPE_PROCESS</param>
            <param name="initial_value">1</param>
            <param name="increment_size">10</param>
            <param name="optimizer">pooled-lo</param>
            <param name="value_column">next_value</param>
            <param name="force_table_use">true</param>
        </generator>
    </id>
    <version name="version" type="int" column="VERSION"/>
    <property name="envelopeId" type="string" length="255">
        <column name="ENVELOPE_ID" not-null="false" unique="false" />
    </property>
    <property name="status" type="string" length="255">
        <column name="STATUS" not-null="false" unique="false" />
    </property>
    <property name="subject" type="string" length="255">
        <column name="SUBJECT" not-null="false" unique="false" />
    </property>
    <set name="events" lazy="false" fetch="select" inverse="true"  cascade="all">
        <cache usage="read-write" region="com.pat.storage.collections"/>
        <key foreign-key="ENVELOPE_EVENT_FKC" not-null="false"   >
            <column name="ENVELOPE_FK"/>
        </key>
        <one-to-many class="com.pat.storage.entities.EnvelopeEvent" not-found="exception"/>
    </set>
    
</class>
public class EnvelopeEvent extends AbstractEntity{

private static final long serialVersionUID = -11111L;
    
private String eventType;

private Date triggerTime;

private EnvelopeProcess envelopeProcess;

public EnvelopeProcess getEnvelopeProcess() {
    return envelopeProcess;
}

public void setEnvelopeProcess(EnvelopeProcess envelopeProcess) {
    this.envelopeProcess = envelopeProcess;
}

public String getEventType() {
    return eventType;
}

public void setEventType(String eventType) {
    this.eventType = eventType;
}

public Date getTriggerTime() {
    return triggerTime;
}

public void setTriggerTime(Date triggerTime) {
    this.triggerTime = triggerTime;
}

}
<class name="com.iqx.storage.entities.EnvelopeEvent" table="ENVELOPE_EVENT" polymorphism="implicit" mutable="true" dynamic-insert="false" dynamic-update="false" >
    <cache usage="read-write" region="com.iqx.storage.entities"/>
    <id name="id" type="long" unsaved-value="null" >
        <column name="ID"/>
        <generator class="org.hibernate.id.enhanced.SequenceStyleGenerator">
            <param name="sequence_name">ZSEQID_ENVELOPE_EVENT</param>
            <param name="initial_value">1</param>
            <param name="increment_size">10</param>
            <param name="optimizer">pooled-lo</param>
            <param name="value_column">next_value</param>
            <param name="force_table_use">true</param>
        </generator>
    </id>
    <version name="version" type="int" column="VERSION"/>
    <property name="eventType" type="string" length="255">
        <column name="EVENT_TYPE" not-null="true" unique="false"   />
    </property>
    <property name="triggerTime" type="timestamp" precision="3">
        <column name="TRIGGER_TIME" not-null="true" unique="false"/>
    </property>
    <many-to-one name="envelopeProcess" class="com.iqx.storage.entities.EnvelopeProcess"  cascade="none" 
        foreign-key="ENVELOPE_EVENT_FKC" not-null="true" lazy="proxy" fetch="select" property-ref="envelopeId">
        <column name="ENVELOPE_FK" not-null="false"  />
    </many-to-one>
</class>
1

There are 1 best solutions below

0
skyman lee On

Problem is solved, adding property-ref to the key tag of the collection is the solution.

<set name="events" table="ENVELOPE_EVENT" lazy="false" fetch="select" inverse="true" cascade="all">
<key foreign-key="ENVELOPE_EVENT_FKC" not-null="false" property-ref="envelopeId">
    <column name="ENVELOPE_FK"/>
</key>
<one-to-many class="com.pat.storage.entities.EnvelopeEvent"/>