У меня есть приложение весенней загрузки. Я создал спецификацию для поиска. Моя сущность Продукт содержит
@OneToOne
@JoinColumn(name="manufacturerID")
private Manufacturer manufacturer;
@OneToMany
@JoinColumn(name="key")
private List<Productattribute> productattributes;
@OneToMany
@JoinColumn(name="key")
private List<DsStatus> dsStatus;
@OneToMany
@JoinColumn(name="key")
private List<Media> medias;
@OneToMany
@JoinColumn(name="key")
private List<Distributormedia> distributormedias;
Мой запрос поиска при выполнении спецификации
select
.....(fields)...........
from
product product0_
inner join
manufacturer manufactur1_
on product0_.manufacturerID=manufactur1_.ManufacturerID
inner join
ds_status dsstatus2_
on product0_.key=dsstatus2_.key
left outer join
media medias3_
on product0_.key=medias3_.key
left outer join
distributormedia distributo4_
on product0_.key=distributo4_.key
where
product0_.IsDeleted=0
and (
product0_.serial in (
select
product5_.serial
from
product product5_
where
product5_.IsDeleted=?
and (
product5_.Status in (
? , ? , ? , ?
)
)
group by
product5_.serial
having
count(product5_.serial)>1
)
)
group by
product0_.key
После выполнения этого запроса ... существует много подзапросов для извлечения детали из таблицы соединений. Если общее количество продукта равно 10, то выполняется 10 подзапросов для дочерней таблицы. Пример:
select
manufactur0_.ManufacturerID as Manufact1_7_0_,
manufactur0_.Address as Address2_7_0_
from
manufacturer manufactur0_
where
manufactur0_.ManufacturerID=?
На самом деле я не хочу подробностей из таблиц соединения. Я хочу только данные из родительской таблицы (продукта). Из-за этого требуется больше времени для возврата результата.
Добавление спецификации
public Specification<Product> findByCriteria(List<Map<CriteriaSpecAttrKeys,Object>> searchCriteria) throws Exception {
List<Predicate> predicates = new ArrayList<>();
return (root, query, cb) -> {
try {
Join<Product, Manufacturer> manufacturer = root.join("manufacturer",JoinType.INNER);
Join<Product, DsStatus> dsStatus = root.join("dsStatus",JoinType.INNER);
Join<Product, Media> media = root.join("medias",JoinType.LEFT);
Join<Product, Distributormedia> distributormedia = root.join("distributormedias",JoinType.LEFT);
predicates.add(cb.equal(root.get("isDeleted"), false));
Subquery<Product> subquery = query.subquery(Product.class);
Root<Product> subroot = subquery.from(Product.class);
Predicate subpredicate1 = cb.equal(subroot.get("isDeleted"),false);
Predicate subpredicate2 = cb.in(subroot.get("status")).value("NEEDS_REVIEW").value("READY_FOR_PROD").value("IS_PROD_AVAIL").value("IN_PROD_NEEDS_REVIEW");
subquery.select(subroot.get("serial")).where(subpredicate1,subpredicate2).groupBy(subroot.get("serial")).having(cb.greaterThan(cb.count(subroot.get("serial")),1L));
predicates.add(cb.in(root.get("serial")).value(subquery));
query.groupBy(root.get("key"));
return cb.and(predicates.toArray(new Predicate[predicates.size()]));
}catch(Exception e) {
throw e;
}
};
}
Заранее спасибо
Обновление Я изменил OneToOne Отображение на
@OneToOne(fetch=FetchType.LAZY)
@JoinColumn(name="manufacturerID")
private Manufacturer manufacturer;
Затем во время выполнения возникла исключительная ситуация.
ERROR 28185 --- [nio-8090-exec-2] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.http.converter.HttpMessageConversionException: Type definition error: [simple type, class org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer]; nested exception is com.fasterxml.jackson.databind.exc.InvalidDefinitionException: No serializer found for class org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) (through reference chain: com.dmp.servicecontroller.response.Response["data"]->java.util.ArrayList[0]->com.product.entities.Product["manufacturer"]->com.manufacturer.entities.Manufacturer_$$_jvst266_1c["handler"])] with root cause
В исключительной ситуации рекомендуется to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS
Поэтому я добавил @JsonIgnore, затем
@JsonIgnore
@OneToOne(fetch=FetchType.LAZY)
@JoinColumn(name="manufacturerID")
private Manufacturer manufacturer;
Это правильный метод?
Мой контроллер
@RestController
@RequestMapping(RestApiUrls.PRODUCT_BASE_URL)
public class ProductController {
@Autowired
SearchSpecification searchSpecification;
@Autowired
ProductRepository productRepository;
@PostMapping(RestApiUrls.SEARCH)
public List<Product> productSearch(@Valid @RequestBody ProductSearchRequest productSearchRequest) {
List<Product> productList = null;
try {
productList = productRepository.findAll(searchSpecification.findByCriteria(new ArrayList<>()));
} catch (Exception e) {
e.printStackTrace();
}
return productList;
}
}