Хочу получить полную информацию о лоте с последним ставившим и текущей ценой используя классы DTO
@Entity
@Table(name = "lot")
public class Lot {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Enumerated(EnumType.STRING)
private Status status;
private String title;
@Min(1)
@Max(4096)
private String description;
@Min(1)
@Max(100)
private Integer startPrice;
@Min(1)
@Max(100)
private Integer bidPrice;
@OneToMany(mappedBy = "lot",fetch = FetchType.EAGER,cascade = CascadeType.ALL)
private List<Bid>bidList;
public Lot(Status status, String title, String description, Integer startPrice, Integer bidPrice) {
this.status = Status.CREATED;
this.title = title;
this.description = description;
this.startPrice = startPrice;
this.bidPrice = bidPrice;
}
public Lot() {
}
@Entity
@Table(name ="bid" )
public class Bid {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String bidderName;
private LocalDateTime timeStamp;
@ManyToOne
@JoinColumn(name = "lot_id")
private Lot lot;
public Bid(String bidderName, LocalDateTime timeStamp, Lot lot) {
this.bidderName = bidderName;
this.timeStamp = timeStamp;
this.lot = lot;
}
public Bid() {
}
public class FullLotDTO {
private Long id;
private String status;
private String title;
private String description;
private Integer startPrice;
private Integer bidPrice;
private Integer currentPrice;
private BidderDTO bidList;
public FullLotDTO(Long id, String status, String title, String description, Integer startPrice, Integer bidPrice, Integer currentPrice, BidderDTO bidList) {
this.id = id;
this.status = status;
this.title = title;
this.description = description;
this.startPrice = startPrice;
this.bidPrice = bidPrice;
this.currentPrice = currentPrice;
this.bidList = bidList;
}
public class BidderDTO {
private String bidderName;
private LocalDateTime timeStamp;
public BidderDTO(String bidderName, LocalDateTime timeStamp) {
this.bidderName = bidderName;
this.timeStamp = timeStamp;
}
@Repository
public interface BidRepository extends JpaRepository<Bid, Integer> {
@Query("SELECT new ru.skypro.lessons.springboot.auction.dto.FullLotDTO " +
"(l.id, " +
"l.status, " +
"l.title, " +
"l.description, " +
"l.startPrice, " +
"l.bidPrice, " +
"SUM(l.startPrice * l.bidPrice) AS currentPrice, " +
"b.bidderName, b.timeStamp) " +
"FROM Bid b JOIN b.lot l " +
"WHERE l.id = :id AND b.timeStamp = (SELECT MAX(b2.timeStamp) FROM Bid b2 WHERE b2.lot = l)" +
"GROUP BY l.id, l.status, l.title, l.description, l.startPrice, l.bidPrice,b.bidderName, b.timeStamp")
FullLotDTO InfoFullLot(@Param("id") Long id);
Имеется две связанные таблицы таблицы и класс DTO который использую для передачи данных и ожидаю возврат информацию о лоте с последним ставившим и текущей ценой, запрос еще должен подсчитать и выдать сумму .
Выдает ошибку
.IllegalStateException: Cannot instantiate class 'ru.skypro.lessons.springboot.auction.dto.FullLotDTO' (it has no constructor with signature [java.lang.Long, ru.skypro.lessons.springboot.auction.model.Status, java.lang.String, java.lang.String, java.lang.Integer, java.lang.Integer, java.lang.Long, java.lang.String, java.time.LocalDateTime], and not every argument has an alias)
Застрял на моменте с составлением запрос к БД так как нету полного понимания как строить запрос.
Подскажите как правильно реализовать запрос.
Ответы (1 шт):
В тесте ошибки сказано and not every argument has an alias
что нет алиасов на полученные колонки (l.id as id и т.д). Формат запроса должен выглядеть так:
@Query("SELECT new ru.skypro.lessons.springboot.auction.dto.FullLotDTO " +
"(l.id as id, " +
"l.status as status, " +
"l.title as title, " +
"l.description as description, " +
"l.startPrice as startPrice, " +
"l.bidPrice as bidPrice, " +
"SUM(l.startPrice * l.bidPrice) AS currentPrice, " +
"b.bidderName as bidderName, " + // должно присутствовать в конструкторе
"b.timeStamp as timeStamp) " + // должно присутствовать в конструкторе
"FROM Bid b JOIN b.lot l " +
"WHERE l.id = :id AND b.timeStamp = (SELECT MAX(b2.timeStamp) FROM Bid b2 WHERE b2.lot = l)" +
"GROUP BY l.id, l.status, l.title, l.description, l.startPrice, l.bidPrice,b.bidderName, b.timeStamp")
FullLotDTO InfoFullLot(@Param("id") Long id);
Конструктор DTO лучше сделать только с примитивными данными, и 2 последних поля которые относятся к другой таблице, лучше преобразовать в объект внутри конструктора:
public class FullLotDTO {
private Long id;
private String status;
private String title;
private String description;
private Integer startPrice;
private Integer bidPrice;
private Long currentPrice;
private BidderDTO bidList;
public FullLotDTO(Long id, String status, String title, String description,
Integer startPrice, Integer bidPrice,
Long currentPrice,
// BidderDTO bidList // этого не должно быть в параметрах конструктора
String bidderName, // поле из запроса
LocalDateTime timeStamp //поле из запроса
) {
this.id = id;
this.status = status;
this.title = title;
this.description = description;
this.startPrice = startPrice;
this.bidPrice = bidPrice;
this.currentPrice = currentPrice;
this.bidList = new BidderDTO(bidderName, timeStamp); // создаем объект тут
}
}