У меня проблема с выбором всего значения из одной таблицы и нескольких других столбцов с помощью Spring Data JPA. Я использую базу данных PostgreSql, и когда я отправляю запрос через PgAdmin, я получаю нужные мне значения, но если я использую его в Spring Boot Rest, возвращает только одно значение таблицы (подзапрос не работает). Что я делаю не так?
@Query(value = "SELECT item.*, MIN(myBid.bid) AS myBid, (SELECT MIN(lowestBid.bid) AS lowestbid FROM bids lowestBid WHERE lowestBid.item_id = item.item_id GROUP BY lowestBid.item_id) FROM item JOIN bids myBid ON item.item_id = myBid.item_id WHERE myBid.user_id = :user_id GROUP BY item.item_id", nativeQuery = true)
public List<Item> findAllWithDescriptionQuery(@Param("user_id") UUID userId);
Добавлен класс предмета
@Data
@Entity(name = "item")
public class Item {
@Id
@GeneratedValue
private UUID itemId;
@NotNull
@Column(name = "title")
@Size(max = 255)
private String title;
@NotNull
@Column(name = "description")
private String description;
@NotNull
@Column(name = "created_user_id")
private UUID createdUserId;
}
@PhilippMerkle, я добавил класс Item
Тип возвращаемого значения - Список объектов Item, а в указанном запросе есть столбцы, которые не являются частью возвращаемого объекта. Я рекомендую использовать соответствующий Entity, который полностью заполняет ваш тип ответа.
Возможно, вы могли бы показать пример, как объединить две таблицы с совпадающими идентификаторами в обеих таблицах с помощью Entity. Потому что я не мог присоединиться.
Результат вашего собственного запроса нельзя просто сопоставить с сущностями из-за агрегирования в базе данных, выполняемого для расчета MIN собственных ставок и MIN других ставок. В частности, ваша сущность Item не несет никаких атрибутов для хранения myBid или lowestbid.
Следовательно, вы хотите вернуть из метода запроса Проекция. Проекция - это простой интерфейс с методами получения, которые точно соответствуют полям, возвращаемым вашим запросом:
public interface BidSummary {
UUID getItem_id();
String getTitle();
String getDescription();
double getMyBid();
double getLowestbid();
}
Обратите внимание, как метод запроса возвращает проекцию BidSummary:
@Query(value = "SELECT item.*, MIN(myBid.bid) AS myBid, (SELECT MIN(lowestBid.bid) AS lowestbid FROM bids lowestBid WHERE lowestBid.item_id = item.item_id GROUP BY lowestBid.item_id) FROM item JOIN bids myBid ON item.item_id = myBid.item_id WHERE myBid.user_id = :user_id GROUP BY item.item_id", nativeQuery = true)
public List<BidSummary> findOwnBids(@Param("user_id") UUID userId);
Спасибо за ваш ответ. Должен ли я писать Projection в моем классе Item или ItemRepository?
Интерфейс BidSummary можно разместить рядом с вашей сущностью Item, то есть в том же пакете. Соответствующий метод запроса можно разместить в любом репозитории JPA, например ItemRepository. BidsRepository, однако, подходит лучше.
Мне нужно использовать какие-то аннотации?
Я получаю эту ошибку: Нет сопоставления диалекта для типа JDBC: 1111; вложенное исключение - org.hibernate.MappingException: Нет сопоставления диалекта для типа JDBC: 1111
Ошибка заключается в том, что Hibernate не знает, как сопоставить UUID с типом данных Postgres. Смотрите здесь для решения: stackoverflow.com/a/28193142/7492402
Спасибо за ответ. Все работает так, как мне нужно. Принимаю твой ответ. Еще раз спасибо за помощь.
Рад, что смог помочь.
Как выглядит класс Item?