Following a previous question:
I have a Patients table mapped by the following class:
public class Patient {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int uid;
@Column(columnDefinition = "VARCHAR(20)")
private String id;
private boolean isId;
private String name;
@ManyToOne
@JoinColumn(name="hmo")
private Hmo hmo;
@ManyToOne
@JoinColumn(name="doctor")
private Doctor doctor;
private Instant openDate;
private String comments;
...
}
And a HMO table mapped by the following class:
public class Hmo {
public static final String UID = "uid";
public static final String NAME = "name";
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int uid;
private String name;
...
}
(Doctor class is similar to HMO) I would like to extract only a subset of the patient: Its id, name and the HMO's name, so I have created a metadata object:
public class PatientMetadata {
public static final String UID = "uid";
public static final String NAME = "name";
private int uid;
private String id;
private boolean isId;
private String name;
private String hmo;
...
}
Trying to fill this object using join and fetch failed, so I have written the following code without any join, and looks like Hibernate is implicitly creating the join:
try (SessionFactory sessionFactory = HibernateUtils.getSessionFactory();
Session session = sessionFactory.openSession()) {
CriteriaBuilder criteriaBuilder = session.getCriteriaBuilder();
CriteriaQuery<PatientMetadata> criteria = criteriaBuilder.createQuery(PatientMetadata.class);
Root<Patient> patientRoot = criteria.from(Patient.class);
Root<Hmo> hmoRoot = criteria.from(Hmo.class);
criteria.select(criteriaBuilder.construct(PatientMetadata.class,
patientRoot.get("uid"),
patientRoot.get("id"),
patientRoot.get("isId"),
patientRoot.get("name"),
hmoRoot.get("name")))
.where(criteriaBuilder.equal(patientRoot.get("hmo"), hmoRoot.get("uid")));
System.out.println(session.createQuery(criteria).getResultList());
}
It looks like the code is working well: I am getting the correct answers, and only a single SQL query is sent to the server.
The problem is that the generated SQL query contains cross join and not inner join:
Hibernate: select patient0_.uid as col_0_0_, patient0_.id as col_1_0_, patient0_.isId as col_2_0_, patient0_.name as col_3_0_, hmo1_.name as col_4_0_ from patients patient0_ cross join hmos hmo1_ where patient0_.hmo=hmo1_.uid
However, according to documentations it is discouraged to use such queries (CROSS JOIN with WHERE), so my question is how can I correctly fill this metadata object correctly?
Should it be an Entity class?
Should I somehow map it with fetch/join?