简体   繁体   中英

JPA - lazy load unidirectional OneToMany not working with discriminator

I'm trying to have a oneToMany relationship between Visit and CrewMember. This CrewMember is a "type of person" and has some specific attributes that are not needed for other types (Passenger for example) -> hence the inheritance

This oneToMany relationship has to be lazy loaded, but when I then get the crewMembers it seems as if my join doesn't take the discriminator into account.

Visit class:

@Entity
@Table(name = "VISIT")
public class Visit {
  @OneToMany
  @JoinColumn(name = "VISIT_ID")
  private List<CrewMember> crewMembers;
}

CrewMember class:

@Entity
@DiscriminatorValue(value = "CREW")
public class CrewMember extends Person {
  @Column(name = "CREW_NUMBER")
  private Integer number;
}

Person class:

@Entity
@Table(name = "PERSON_ON_BOARD")
@DiscriminatorColumn(name = "TYPE_PERSON_ON_BOARD")
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
public class Person {
  ...
}

I've created a method to find those crewMembers like this:

@Stateless
public class PeopleOnBoardRepositoryBean implements PeopleOnBoardRepository {

  @Override
  public List<CrewMember> findCrewMembers(long visitId) {
    TypedQuery<Visit> query =  em().createQuery("SELECT v FROM Visit v JOIN fetch v.crewMembers WHERE v.id = :visitId", Visit.class);
    query.setParameter("visitId", visitId);
    Visit visit = query.getSingleResult();
    return visit.getCrewMembers();
  }
}

But the result always contains ALL the persons (crewMembers, passengers) instead of only the crewMembers.. Why is that and what am I doing wrong?

If I'm trying to do it the "normal way which I would think that should work" like:

public List<CrewMember> findCrewMembers(long visitId) {
    TypedQuery<Visit> query =  em().createQuery("SELECT v FROM Visit v  WHERE v.id = :visitId", Visit.class);
    query.setParameter("visitId", visitId);
    Visit visit = query.getSingleResult();
    return visit.getCrewMembers();
}

then I'm getting:

org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: be.fgov.health.msw.domain.visit.Visit.crewMembers, no session or session was closed

EDIT :

After adding:

Visit visit = query.getSingleResult();
visit.getCrewMembers.size();
return visit.getCrewMembers();

I've got the LazyInitializationException fixed. This was needed to fetch all the crewMembers. Otherwise I was just passing a pointer to the arrayList without prefetched elements hence the LazyInitializationException.

The problem with the discriminator is still there though.. I'm getting ALL the persons instead of only the crewMembers. I've also tried adding:

@ForceDiscriminator 

on my Person class but this doesn't change anything. I've read that on http://www.gmarwaha.com/blog/2009/08/26/hibernate-why-should-i-force-discriminator/

EDIT 2:

I've "fixed" (workaround) the discriminator column by adding:

@OneToMany
@JoinColumn(name = "VISIT_ID")
@Where(clause="TYPE_PERSON_ON_BOARD = 'CREW'")
private List<CrewMember> crewMembers;

The @Where fixes this but I actually find this extremely ugly. Isn't there any other way to do this?

您需要在事务(会话)的边界内访问实体bean,否则结果将被分离,从而导致惰性异常

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM