Hi,
I use Hibernate 3.4.0 and I create sql statement with Criteria API.
There are two Entities - ResourceEntry and ActorAccessRecord. They have an optional oneToMany (1, 0...*) association. As FetchMode Join is selected.
It runs into a problem, if the cardinality of ActorAccessRecord is "0". In this case, I got null result-set from query, because
Code:
"inner join T_ACTOR_ACCESS_LOGS actoracces2_
on resourceen1_.C_RESOURCE_ENTRY_ID=actoracces2_.C_RESOURCE_ENTRY_ID"
is always false.
According to the defination of FetchMode.Join, Hibernate schould generate an outer join for this association, but it generates an inner join instead
(see the sql below).
Code:
Hibernate:
select
this_.C_OBSERVATION_CONTEXT_ID as C1_31_2_,
this_.C_OBSERVATION_AREA_CODE as C2_31_2_,
this_.C_OBSERVATION_UNIT_CODE as C3_31_2_,
this_.C_SURVEY_CODE as C4_31_2_,
this_.C_STATISTICS_CODE as C5_31_2_,
this_.C_STATUS as C6_31_2_,
this_.version as version31_2_,
resourceen1_.C_RESOURCE_ENTRY_ID as C1_40_0_,
resourceen1_.C_USER_TYPE as C25_40_0_,
resourceen1_.version as version40_0_,
actoracces2_.C_ACTOR_ACCESS_LOG_ID as C1_30_1_,
actoracces2_.C_ACTOR_URI as C2_30_1_,
actoracces2_.C_READ_ACCESS as C3_30_1_,
actoracces2_.version as version30_1_,
actoracces2_.C_WRITE_ACCESS as C5_30_1_
from
T_OBSERVATION_CONTEXTS this_
inner join
T_RESOURCE_ENTRIES resourceen1_
on this_.C_OBSERVATION_CONTEXT_ID=resourceen1_.C_OBSERVATION_CONTEXT_ID
inner join
T_ACTOR_ACCESS_LOGS actoracces2_
on resourceen1_.C_RESOURCE_ENTRY_ID=actoracces2_.C_RESOURCE_ENTRY_ID
where
this_.C_SURVEY_CODE=?
and this_.C_STATISTICS_CODE=?
and this_.C_OBSERVATION_AREA_CODE=?
and actoracces2_.C_ACTOR_URI<>?
Hier is a snippert of the creation of criteria
Code:
Criteria criteriaEntry = criteria.createCriteria("resourceEntries");
criteriaEntry.setFetchMode("actorAccessRecords", FetchMode.JOIN);
....
if ( ResourceSelectorUtils.hasAccessActorURI(selector)){
Criteria criteriaActor = criteriaEntry.createCriteria("businessLog.actorAccessRecords");
// invertReadActor
if (selector.isInvertReadActorURISearch()){
criteriaActor.add(Restrictions.ne("actorURI", selector.getAccessActorURI()));
}
else{
criteriaActor.add(Restrictions.eq("actorURI", selector.getAccessActorURI()));
}
...
The following is my mapping
Code:
@Entity
@Table(name = ENTITY.T_RESOURCE_ENTRIES.TABLE)
public class ResourceEntry extends AbstractManagedDomainObject{
private BusinessLog businessLog;
....
}
Code:
@Embeddable
public class BusinessLog implements DomainObject {
/**
* The access records associated with the resource
*/
private List <ActorAccessRecord> actorAccessRecords;
public BusinessLog() {
this.actorAccessRecords = new LinkedList <ActorAccessRecord>();
}
@OneToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REMOVE})
@JoinColumn(name = ENTITY.T_ACTOR_ACCESS_LOGS.C_RESOURCE_ENTRY_ID, nullable = false)
@OptimisticLock(excluded = true)
public List <ActorAccessRecord> getActorAccessRecords() {
return this.actorAccessRecords;
}
....
}
Code:
@Entity
@Table(name = ENTITY.T_ACTOR_ACCESS_LOGS.TABLE)
public class ActorAccessRecord extends AbstractManagedDomainObject {
....
}
Do you have any suggestion to solve this problem?
Thany you in advance,
mzha