Присоединить частичный составной ключ в JPA Hibernate - PullRequest
0 голосов
/ 24 января 2019

Я использую JPA для определения модели данных для базы данных с составными ключами. Я не могу изменить базу данных.

У меня есть Car сущность с составным ключом (carType и carId). Второй (необязательный) объект PorscheInfo содержит дополнительную информацию для автомобилей Porsche. К сожалению, соответствующая таблица "porsche_info" не содержит столбца, содержащего информацию carType, поскольку ее записи относятся исключительно к CarType = 'Porsche'.

SQL для этой операции прост:

SELECT *
FROM cars
LEFT JOIN porsche_info
ON cars.CarId = porsche_info.CarId
    AND cars.CarType = 'Porsche'

Как я могу перевести это в правильную настройку JPA?

Пока у меня есть следующие классы сущностей:

@Embeddable
public class CarKey {
    private String carType;

    private String carId;
}

@Entity(name = "cars")
public class Car {
    @EmbeddedId
    private CarKey key;

    // car information

    @OneToOne
    @JoinColumn(name = "CarId", referencedColumnName = "CarId")
    private PorscheInfo porscheInfo;
    // or
    @OneToMany
    @JoinColumn(name = "CarId", referencedColumnName = "CarId")
    private Set<PorscheInfo> porscheInfo;
}

@Embeddable
public class PorscheInfoKey {
    private String carId;
}

@Entity (name = "porsche_info")
public class PorscheInfo {
    @EmbeddedId
    private PorscheInfoKey key;

    // porsche info
}

Было бы предпочтительнее решение @OneToOne, но решение @OneToMany (из-за различных классов ключей) также является жизнеспособным.

CriteriaQuery выглядит так:

CriteriaBuilder cb = entityManager.getCriteriaBuilder();

CriteriaQuery<Car> carQuery = cb.createQuery(Car.class).distinct(true);
Root<Car> carRoot = carQuery.from(Car.class);

carQuery.select(carRoot);
carRoot.fetch("porscheInfo", JoinType.LEFT);
  • В подходе @OneToOne я получаю: org.hibernate.MappingException: повторяющийся столбец в сопоставлении для сущности: Car column: CarId (должен отображаться с помощью insert = "false" update = "false")
  • В подходе @OneToMany я получаю: org.hibernate.AnnotationException: referencedColumnNames (CarId) из PorscheInfo.porscheInfo, ссылающийся на Car, не сопоставленный с одним свойством

Как должна выглядеть правильная настройка JPA? Я не знаю, как сказать Hibernate, какие столбцы должны быть объединены. Я думал о .multiselect() или Join<Car, PorscheInfo> ... .on() подходах, но не заставил его работать.

редактирование: Я получил @OneToOne подход к работе с оговоркой:

@OneToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "CarId", referencedColumnName = "CarId", insertable = false, updatable = false)
private PorscheInfo porscheInfo;

Странное поведение: у всех автомобилей Porsche свойство porscheInfo правильно инициализировано из-за carRoot.fetch("porscheInfo", JoinType.LEFT);. Однако все автомобили не Porsche выдают исключение LazyInitializationException, когда я пытаюсь получить доступ к их свойству porscheInfo. Стремительная выборка нежелательна, поскольку приводит к дополнительному ненужному запросу для каждого автомобиля (1 + N запросов).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...