Я создаю веб-приложение. Я недавно добавил фильтр страны на стороне интерфейса. Теперь я хочу использовать параметр запроса для вызова соответствующего CrudRepository в бэкэнде. В вызов я хочу включить спецификацию, которая включает в себя текст, извлеченный из параметра запроса.
Пример:
Пользователь устанавливает для фильтра страны значение «ether».
Ожидание: я хочу, чтобы в ответ было включено объявление, в котором есть место с адресом, на котором указана страна = "Нидерланды".
Ситуация: я вижу, что в журнал записывается следующий запрос Hibernate:
2020-02-17 20: 01: 10.720 DEBUG 4088 --- [nio-8080-exe c -5] org.hibernate. SQL: выберите файл классифицированного_0 в качестве id1_0_, классифицированного__. описание как descript2_0_, классифицировано как 0_3__ценка, классифицировано как цена____, классифицировано как итоговое значение_0_, классифицировано как идентификатора_0_, классифицировано как класс_ классификатора_0_ из классифицированного классифицированного места перекрестного соединения0_1, где классифицировано0_.id = place1_.id и (например, place1_.country?)
... и не получить результатов.
Мне кажется, проблема в том, что мы ищем записи, где классифицированные.id == место. id . Я на самом деле хочу искать записи, где классифицированный.ид == место. секретный_ид . Я также не уверен насчет перекрестного соединения ...
Скриншоты (некоторые столбцы для краткости опущены во втором):
Сущности:
@Entity
public class Classified {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private long id;
private String summary;
private String description;
private double price;
@OneToMany(cascade = CascadeType.ALL)
@JoinColumn(name = "classified_id")
private List<ImageMetadata> imageMetadata = new ArrayList<>();
@OneToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "classified_id")
private ThumbnailMetadata thumbnailMetadata;
public Place getPlace() {
return place;
}
@OneToOne
@JoinColumn(name = "id")
private Place place;
public Classified() { }
public Classified(String summary, String description, double price, String currency) {
this.summary = summary;
this.description = description;
this.price = price;
}
public ThumbnailMetadata getThumbnailMetadata() {
return thumbnailMetadata;
}
public void setThumbnailMetadata(ThumbnailMetadata thumbnailMetadata) {
this.thumbnailMetadata = thumbnailMetadata;
}
public List<ImageMetadata> getImageMetadata() {
return imageMetadata;
}
public void setImageMetadata(List<ImageMetadata> imageMetadata) {
this.imageMetadata = imageMetadata;
}
public void setId(long id) {
this.id = id;
}
public void setPrice(double price) {
this.price = price;
}
public long getId() {
return id;
}
public String getSummary() {
return summary;
}
public void setSummary(String summary) {
this.summary = summary;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public double getPrice() {
return price;
}
}
@Entity
public class Place {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private long id;
@Embedded
private Address address;
@OneToOne
@JoinColumn(name = "classified_id")
private Classified classified;
private double latitude;
private double longitude;
private String label;
public Place(Address address, Classified classified, double latitude, double longitude, String label) {
this.address = address;
this.classified = classified;
this.latitude = latitude;
this.longitude = longitude;
this.label = label;
}
public Place(Classified classified, Address address) {
this.classified = classified;
this.address = address;
}
public Place() {
}
public long getId() {
return id;
}
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
public double getLatitude() {
return latitude;
}
public void setLatitude(double latitude) {
this.latitude = latitude;
}
public double getLongitude() {
return longitude;
}
public void setLongitude(double longitude) {
this.longitude = longitude;
}
public String getLabel() {
return label;
}
public void setLabel(String label) {
this.label = label;
}
}
@Embeddable
public class Address {
private String country;
private String countryCode;
private String state;
private String city;
private String suburb;
private String town;
private String county;
private String postcode;
private String hamlet;
private String village;
private String stateDistrict;
public Address() {
}
public Address(String country, String countryCode, String state, String city, String suburb, String town,
String county, String postcode, String hamlet, String village, String stateDistrict) {
this.country = country;
this.countryCode = countryCode;
this.state = state;
this.city = city;
this.suburb = suburb;
this.town = town;
this.county = county;
this.postcode = postcode;
this.hamlet = hamlet;
this.village = village;
this.stateDistrict = stateDistrict;
}
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
public String getCountryCode() {
return countryCode;
}
public void setCountryCode(String countryCode) {
this.countryCode = countryCode;
}
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getSuburb() {
return suburb;
}
public void setSuburb(String suburb) {
this.suburb = suburb;
}
public String getTown() {
return town;
}
public void setTown(String town) {
this.town = town;
}
public String getCounty() {
return county;
}
public void setCounty(String county) {
this.county = county;
}
public String getPostcode() {
return postcode;
}
public void setPostcode(String postcode) {
this.postcode = postcode;
}
public String getHamlet() {
return hamlet;
}
public void setHamlet(String hamlet) {
this.hamlet = hamlet;
}
public String getVillage() {
return village;
}
public void setVillage(String village) {
this.village = village;
}
public String getStateDistrict() {
return stateDistrict;
}
public void setStateDistrict(String stateDistrict) {
this.stateDistrict = stateDistrict;
}
}
@Entity
public class ImageMetadata {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private long id;
private String path;
private String filename;
@ManyToOne
@JoinColumn(name="classified_id")
private Classified classified;
public Classified getClassified() {
return classified;
}
public void setClassified(Classified classified) {
this.classified = classified;
}
public ImageMetadata() {
}
public ImageMetadata(String path) {
this.path = path;
}
public ImageMetadata(FileMetadata fileMetadata) {
this.path = fileMetadata.getPath();
this.filename = fileMetadata.getFilename();
}
public String getFilename() {
return filename;
}
public void setFilename(String filename) {
this.filename = filename;
}
public long getId() {
return id;
}
public String getPath() {
return path;
}
}
@Entity
public class ThumbnailMetadata {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private long id;
private String path;
private String filename;
@ManyToOne
@JoinColumn(name="classified_id")
private Classified classified;
public Classified getClassified() {
return classified;
}
public void setClassified(Classified classified) {
this.classified = classified;
}
public ThumbnailMetadata() {
}
public ThumbnailMetadata(String path) {
this.path = path;
}
public ThumbnailMetadata(FileMetadata fileMetadata) {
this.path = fileMetadata.getPath();
this.filename = fileMetadata.getFilename();
}
public void setPath(String path) {
this.path = path;
}
public String getFilename() {
return filename;
}
public void setFilename(String filename) {
this.filename = filename;
}
public long getId() {
return id;
}
public String getPath() {
return path;
}
}
Репозиторий:
@Repository
public interface ClassifiedRepository extends CrudRepository<Classified, Long>, JpaSpecificationExecutor<Classified> {}
Спецификация:
public class ClassifiedCountrySpecification implements Specification<Classified> {
private final String countryString;
public ClassifiedCountrySpecification(String countryString) {
this.countryString = countryString;
}
@Override
public Predicate toPredicate(Root<Classified> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) {
return criteriaBuilder.like(root.get("place").get("address").get("country"), "%" + countryString + "%");
}
}