CriteriaQuery JOIN

Помогите, пожалуйста, составить запрос типа:

select dmp_id, dmp_dr_id, dmp_permit_id, dmp_dsc,
       p.name as permit_name,
from dat_map_permit dmp
join permit p on p.id = dmp_permit_id
where dmp.dmp_dr_id = ?

Не могу понять где будет определён join permit p on p.id = dmp_permit_id. Мой запрос:

    CriteriaBuilder cb = em.getCriteriaBuilder();
    CriteriaQuery<MapPermitDto> cq = cb.createQuery(MapPermitDto.class);
    Root<MapPermitEntity> root = cq.from(MapPermitEntity.class);
    Join<MapPermitEntity, PermitEntity> permitIdJoin = root.join(MapPermitEntity_.permId);
    cq.multiselect(
            root.get(MapPermitEntity_.id).alias(MapPermitEntity_.ID),
            root.get(MapPermitEntity_.drid).alias(MapPermitEntity_.DRID),
            root.get(MapPermitEntity_.permid).alias(MapPermitEntity_.PERMID),
            root.get(MapPermitEntity_.dsc).alias(MapPermitEntity_.DSC),

            permitIdJoin.get(PermitEntity_.name).alias("permitName"));
    cq.where(cb.equal(root.get(MapPermitEntity_.DRID), mapPermitDto.getDrid()));

Ответы (2 шт):

Автор решения: kent

В принципе было всё правильно, но в DTO было несовпадение типа данных.

    CriteriaBuilder cb = em.getCriteriaBuilder();
    CriteriaQuery<MapPermitDto> cq = cb.createQuery(MapPermitDto.class);
    Root<MapPermitEntity> root = cq.from(MapPermitEntity.class);
    Join<MapPermitEntity, PermitEntity> permitIdJoin = root.join(MapPermitEntity_.permId);
    cq.multiselect(
            root.get(MapPermitEntity_.id).alias(MapPermitEntity_.ID),
            root.get(MapPermitEntity_.drid).alias(MapPermitEntity_.DRID),
            root.get(MapPermitEntity_.permid).alias(MapPermitEntity_.PERMID),
            root.get(MapPermitEntity_.valb).alias(MapPermitEntity_.VALB),
            root.get(MapPermitEntity_.vali).alias(MapPermitEntity_.VALI),
            root.get(MapPermitEntity_.valc).alias(MapPermitEntity_.VALC),
            root.get(MapPermitEntity_.dsc).alias(MapPermitEntity_.DSC),

            
            permitIdJoin.get(PermitEntity_.name).alias(PermitEntity_.NAME),
            permitIdJoin.get(PermitEntity_.dsc).alias("permDsc"),
            permitIdJoin.get(PermitEntity_.rModulesid).alias(PermitEntity_.R_MODULESID),
            permitIdJoin.get(PermitEntity_.typ).alias(PermitEntity_.TYP)
            );
    cq.where(cb.equal(root.get(MapPermitEntity_.DRID), mapPermitDto.getDrid()));
    try {
        return em.createQuery(cq).getResultList();
    } catch (NoResultException e) {
        return null;
    }
→ Ссылка
Автор решения: amala

Не могу понять где будет определён join permit p on p.id = dmp_permit_id.

Насколько я понял поле присоединяемой таблицы определяется через JPA-связь (например, @OneToOne).

Если попытаться присоединить таблицу по полю без JPA-связи, то Criteria API бросает исключение org.hibernate.query.criteria.internal.BasicPathUsageException

Мой код

        CriteriaBuilder cb = s.getCriteriaBuilder();
        CriteriaQuery<DTO> dmpCriteria = cb.createQuery(DTO.class);
        Root<DMP> dmpRoot = dmpCriteria.from(DMP.class);
        Join<DMP, Permit> tasks = dmpRoot.join("dmp_permit_id");
        dmpCriteria.where(cb.equal(dmpRoot.get("dmp_dr_id"), 3));
        Join<DMP, Permit> permitIdJoin = dmpRoot.join("dmp_permit_id");
        dmpCriteria.multiselect(
            dmpRoot.get("dmp_id"),
                dmpRoot.get("dmp_dr_id"),
                dmpRoot.get("dmp_permit_id"),
                dmpRoot.get("dsc"),
                permitIdJoin.get("id")
        );
        TypedQuery<DTO>t  = s.createQuery(dmpCriteria);
        List<DTO> dmpList = t.getResultList();

Сущности

MapPermitEntity

@Entity
@Table(name = "dmp_map_permit")
public class DMP {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long dmp_id;

    private Long dmp_dr_id;

    private String dsc;

    @OneToOne
    @JoinColumn(name = "dmp_permit_id")
    private Long dmp_permit_id;
...

Permit

@Entity
@Table(name = "permit")
public class Permit {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    private String name;
→ Ссылка