Hibernate Criteria API объединяет объекты без какой-либо связи - PullRequest
0 голосов
/ 24 марта 2020

Я пытаюсь написать Hibernate Criteria API, эквивалентный следующему SQL запросу:

select c.NAME         as carName,
   cc.COLOR_CODE      as colorCode,
   cc.COLOR           as color,
   c.DESCRIPTION      as desc,
   c.MANUFACTURE_YEAR as year
from CAR c
     LEFT JOIN CAR_COLOR CC on c.COLOR_CODE_ID = CC.ID
WHERE CC.COLOR_CODE = ?

Это моя Car сущность

public class Car extends BaseEntity {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    private String name;

    @Basic
    @Column(name = "MANUFACTURE_YEAR")
    private String year;

    @Basic
    @Column(name = "DESCRIPTION")
    private String desc;
    private Long colorCodeId;
    private String manufacturer;
}

, и это моя CarColor сущность

public class CarColor extends BaseEntity {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    private String color;
    private String colorCode;
}

Car.colorCodeId - это внешний ключ, который ссылается на CarColor.id. Хотя нет очевидных отношений на уровне сущности, и я не могу добавить никаких связей.

Я хочу сделать левое соединение между этими двумя таблицами / сущностями и отобразить результат в CarSearch? Как бы я это сделал? Очень признателен.

public class CarSearch {
    private String carName;
    private String colorCode;
    private String color;
    private String desc;
    private String year;
}

1 Ответ

0 голосов
/ 24 марта 2020

Декартово произведение может использоваться

CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<Object[]> query = cb.createQuery(Object[].class);
Root<Car> car = query.from(Car.class);
Root<CarColor> carColor = query.from(CarColor.class);

Predicate joinPredicate = cb.equal(car.get("colorCodeId"), carColor.get("id"));

query.multiselect(
    car.get("name"),
    carColor.get("colorCode"),
    carColor.get("color"),
    car.get("desc"),
    car.get("year")
).where(
    joinPredicate, 
    cb.equal(carColor.get("colorCode"), "yourColorCode")
);

Чтобы избежать Object[] в результате запроса, вы должны создать QueryResultDto класс с соответствующим конструктором и использовать этот способ

CriteriaQuery<QueryResultDto> query = cb.createQuery(QueryResultDto.class);
//...
query.select(cb.construct(QueryResultDto.class, 
    car.get("name"),
    carColor.get("colorCode"),
    carColor.get("color"),
    car.get("desc"),
    car.get("year")
));
...