#sql #spring-boot #hibernate #spring-data-jpa
#sql #весенняя загрузка #спящий режим #spring-data-jpa
Вопрос:
Я создал класс AttributeConverter, который преобразует Enum в значение DB и переопределяет необходимые методы. Если я использую JPA-запрос, как показано ниже, вызывается конвертер и получает правильный результат.
public List<Driver> findByStatus(DriverStatus status);
НО если я использую с аннотацией запроса, этот AttributeConverter не вызывается. У меня есть более сложный запрос, в котором мне нужно использовать собственный запрос с преобразователем атрибутов, но у меня это не работает.
@Query(value = "select * from driver where status=:status", nativeQuery = true)
public List<Driver> findByStatus1(DriverStatus status);
есть ли какой-либо способ выполнить это требование?
Обновление 1 — ниже приведен код конвертера
@Converter(autoApply = true)
public class DriverStatusConverter implements AttributeConverter<DriverStatus, String> {
@Override
public String convertToDatabaseColumn(DriverStatus driverStatus) {
if (driverStatus == null) {
return null;
}
System.err.println("from converter" driverStatus.getCode());
return driverStatus.getCode();
}
@Override
public DriverStatus convertToEntityAttribute(String code) {
if (code == null) {
return null;
}
return Stream.of(DriverStatus.values()).filter(c -> c.getCode().equals(code)).findFirst()
.orElseThrow(IllegalArgumentException::new);
}
}
Комментарии:
1. Если возможно, не могли бы вы
converter
entity
также предоставить фрагмент кода and ?2. добавлен код для вопроса @Sujitmohanty30
3. спасибо, но я также хотел бы, чтобы вы также добавили объект.
Ответ №1:
Столкнулся с подобной проблемой, не смог найти удовлетворительного решения, поэтому пришлось прибегнуть к уродливому взлому… Подпись метода репозитория была изменена следующим образом:
public List<Driver> findByStatus1(Integer status);
…и вызывался так:
repository.findByStatus1(DriverStatus.YOUR_DESIRED_STATUS.getCode());
Да, это некрасиво и отчасти противоречит цели AttributeConverter, но, по крайней мере, это работает. В моем конкретном случае мне пришлось прибегнуть к таким мерам только с одним собственным запросом. AttributeConverter по-прежнему работает для всех других запросов JPA.
Ответ №2:
Я просто сталкиваюсь с той же проблемой и использую следующее, чтобы обойти ее
DriverStatusConverter
переместить логический код в convertToEntityAttribute
общедоступный статический метод:
@Override
public DriverStatus convertToEntityAttribute(String code) {
return convertStringToEnum(code);
}
public static DriverStatus convertStringToEnum(String code) {
if (code == null) {
return null;
}
return Stream.of(DriverStatus.values()).filter(c -> c.getCode().equals(code)).findFirst()
.orElseThrow(IllegalArgumentException::new);
}
создать новый DriverDTO
для результата собственного запроса
public interface DriverDTO {
public Integer getId();
public String getName();
public String getStatusCode();
default DriverStatus getStatus() {
return DriverStatusConverter.convertStringToEnum(getStatusCode());
}
}
DriverRepository
findByStatusCode() выбирает столбцы в запросе и возвращает DriverDTO
класс
@Query(value = "select id, name, status as statusCode from driver WHERE status=:statusCode", nativeQuery = true)
public List<DriverDTO> findByStatusCode(String statusCode);
Ответ №3:
Удалите nativeQuery = true
и попробуйте.
@Query(value = "select * from driver where status=:status")
public List<Driver> findByStatus1(DriverStatus status);
В качестве альтернативы вы можете попробовать использовать entityManager
вот так —
Это всего лишь пример кода.
TypedQuery<Trip> q = entityManager.createQuery("SELECT t FROM Trip t WHERE t.vehicle = :v", Trip.class);
q.setParameter("v", Vehicle.PLANE);
List<Trip> trips = q.getResultList();
Ссылка —
https://thorben-janssen.com/jpa-21-type-converter-better-way-to /
Комментарии:
1. Предлагаемый запрос недопустим JPQL
2. Вы говорите о втором? Это был всего лишь пример того, как вы можете использовать
entityManager
для создания запроса. Я уже упоминал в ответе, что это был всего лишь образец. По сути, идея в том, что я хотел, чтобы вы попробовали использоватьentityManager
.3. Я говорю о первом
4. Как это неправильно? Вот ссылка: baeldung.com/spring-data-jpa-query
5.
select * from driver where status=:status
является собственным SQL-запросом. Вы не можете просто удалитьnativeQuery = true
и ожидать, что это сработает. В ссылке, на которую вы ссылаетесь, запросы дляnativeQuery = true
иnativeQuery = false
отличаются