I am trying to map a JPA (using Hibernate) one-to-one relationship with a inheritance strategy TABLE_PER_CLASS. Here is an example:
@Entity
public class DrivingLicense {
@OneToOne(targetEntity = Human.class, cascade = CascadeType.ALL, fetch=FetchType.LAZY)
@JoinColumn
private Human human;
@SuppressWarnings("unchecked")
public static List<DrivingLicense> findMansDrivingLicenses(Long id) {
if (id == null) return null;
return entityManager()
.createQuery("select o from DrivingLicense o left join fetch o.human where o.id = :id")
.setParameter("id", id)
.getResultList();
}
}
@Entity
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public abstract class Human {
...
}
@Entity
public class Man extends Human {
...
}
@Entity
public class Mutant extends Human {
...
}
When I call "findMansDrivingLicenses" to retrieve all man's driving licenses hibernate does a "UNION ALL" with both tables (MAN and MUTANT). Follow the log output:
select
drivinglic0_.id as id3_0_,
human1_.id as id0_1_,
drivinglic0_.first_name as first2_3_0_,
drivinglic0_.human as human3_0_,
drivinglic0_.last_name as last3_3_0_,
drivinglic0_.type as type3_0_,
drivinglic0_.version as version3_0_,
human1_.version as version0_1_,
human1_.comment as comment1_1_,
human1_.behavior as behavior2_1_,
human1_.clazz_ as clazz_1_
from
driving_license drivinglic0_
left outer join
(
select
id,
version,
comment,
null as behavior,
1 as clazz_
from
ma开发者_StackOverflow社区n
union
all select
id,
version,
null as comment,
behavior,
2 as clazz_
from
mutant
) human1_
on drivinglic0_.human=human1_.id
where
drivinglic0_.id=?
Is there any way to prevent hibernate to do this "UNION ALL" and only join with MAN table?
Try to use class
select o from DrivingLicense o left join fetch o.human human where o.id = :id and human.class = Man
UPDATE
retrieve your relationship with Native queries
session = sessionFactory.openSession();
StringBuilder query = new StringBuilder();
query
.append("select ")
.append("{driving.*}, {man.*} ")
.append("from ")
.append("DrivingLicense driving ")
.append("left join ")
.append("Man man ")
.append("on ")
.append("driving.human_id = man.id ")
.append("where ")
.append("driving.id = :id");
Query _query = session.createSQLQuery(query.toString())
/**
* It means: driving alias WILL BE MAPPED TO DrivingLicense Entity
*/
.addEntity("driving", DrivingLicense.class)
/**
* It means: man alias WILL BE MAPPED TO human property of DrivingLicense Entity
*/
.addJoin("man", "driving.human")
.setParameter("id", <DRIVING_LICENSE_ID_GOES_HERE>);
Object [] resultArray = query.list.get(0);
session.close();
And
DrivingLicense driving = resultArray[0];
/**
* YES, Man IS NOT automatically MAPPED TO driving.human property
* You have to set up manually
*/
Man man = resultArray[1];
driving.setHuman(man);
精彩评论