I created an API, it's called search stores feature. .
When I Use this SQL Script runs in MySql. It will show the valid result
SET @productName = null;
SET @BranchName = null;
SET @minPrice = 0;
SET @maxPrice = 10000;
SET @quantity = 1000;
SELECT * FROM stores s
INNER JOIN products p
ON p.id = s.product_id
INNER JOIN branches b
ON b.id = s.branch_id
WHERE (p.name LIKE CONCAT('%', @productName , '%') OR @productName IS NULL)
AND (b.name LIKE CONCAT('%', @branchName , '%') OR @branchName IS NULL)
AND (@minPrice <= p.price AND p.price <= @maxPrice)
AND s.quantity <= @quantity
ORDER BY p.name, b.name, quantity;
.
When I call it by Frontend it happens the log in StoreService.java is...
productName: null, minPrice: 0.0, maxPrice: 15000.0, branchName: null, 1000
Hibernate: SELECT * FROM stores s INNER JOIN products p ON p.id = s.product_id INNER JOIN branches b ON b.id = s.branch_id WHERE (p.name LIKE CONCAT('%', ? , '%') OR ? IS NULL) AND (b.name LIKE CONCAT('%', ? , '%') OR ? IS NULL) AND (? <= p.price AND p.price <= ?) AND s.quantity <= ? ORDER BY p.name
Stores: []
.
Postman Params image
When call it by Postman will get
java.lang.StackOverflowError: null
at com.mysql.cj.jdbc.ClientPreparedStatement.executeInternal(ClientPreparedStatement.java:944) ~[mysql-connector-java-8.0.19.jar:8.0.19]
at com.mysql.cj.jdbc.ClientPreparedStatement.executeQuery(ClientPreparedStatement.java:1003) ~[mysql-connector-java-8.0.19.jar:8.0.19]
at com.zaxxer.hikari.pool.ProxyPreparedStatement.executeQuery(ProxyPreparedStatement.java:52) ~[HikariCP-3.4.2.jar:na]
at com.zaxxer.hikari.pool.HikariProxyPreparedStatement.executeQuery(HikariProxyPreparedStatement.java) ~[HikariCP-3.4.2.jar:na]
at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.extract(ResultSetReturnImpl.java:57) ~[hibernate-core-5.4.10.Final.jar:5.4.10.Final]
at org.hibernate.loader.plan.exec.internal.AbstractLoadPlanBasedLoader.getResultSet(AbstractLoadPlanBasedLoader.java:390) ~[hibernate-core-5.4.10.Final.jar:5.4.10.Final]
at org.hibernate.loader.plan.exec.internal.AbstractLoadPlanBasedLoader.executeQueryStatement(AbstractLoadPlanBasedLoader.java:163) ~[hibernate-core-5.4.10.Final.jar:5.4.10.Final]
at org.hibernate.loader.plan.exec.internal.AbstractLoadPlanBasedLoader.executeLoad(AbstractLoadPlanBasedLoader.java:104) ~[hibernate-core-5.4.10.Final.jar:5.4.10.Final]
at org.hibernate.loader.collection.plan.AbstractLoadPlanBasedCollectionInitializer.initialize(AbstractLoadPlanBasedCollectionInitializer.java:87) ~[hibernate-core-5.4.10.Final.jar:5.4.10.Final]
at org.hibernate.persister.collection.AbstractCollectionPersister.initialize(AbstractCollectionPersister.java:707) ~[hibernate-core-5.4.10.Final.jar:5.4.10.Final]
at org.hibernate.event.internal.DefaultInitializeCollectionEventListener.onInitializeCollection(DefaultInitializeCollectionEventListener.java:76) ~[hibernate-core-5.4.10.Final.jar:5.4.10.Final]
at org.hibernate.event.service.internal.EventListenerGroupImpl.fireEventOnEachListener(EventListenerGroupImpl.java:108) ~[hibernate-core-5.4.10.Final.jar:5.4.10.Final]
at org.hibernate.internal.SessionImpl.initializeCollection(SessionImpl.java:2145) ~[hibernate-core-5.4.10.Final.jar:5.4.10.Final]
at org.hibernate.collection.internal.AbstractPersistentCollection$4.doWork(AbstractPersistentCollection.java:589) ~[hibernate-core-5.4.10.Final.jar:5.4.10.Final]
at org.hibernate.collection.internal.AbstractPersistentCollection.withTemporarySessionIfNeeded(AbstractPersistentCollection.java:264) ~[hibernate-core-5.4.10.Final.jar:5.4.10.Final]
at org.hibernate.collection.internal.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:585) ~[hibernate-core-5.4.10.Final.jar:5.4.10.Final]
at org.hibernate.collection.internal.AbstractPersistentCollection.read(AbstractPersistentCollection.java:149) ~[hibernate-core-5.4.10.Final.jar:5.4.10.Final]
at org.hibernate.collection.internal.PersistentSet.hashCode(PersistentSet.java:458) ~[hibernate-core-5.4.10.Final.jar:5.4.10.Final]
at com.g_able.back_g_exam.entity.Product.hashCode(Product.java:12) ~[classes/:na]
at com.g_able.back_g_exam.entity.Store.hashCode(Store.java:13) ~[classes/:na]
at java.util.HashMap.hash(HashMap.java:339) ~[na:1.8.0_172]
at java.util.HashMap.put(HashMap.java:612) ~[na:1.8.0_172]
at java.util.HashSet.add(HashSet.java:220) ~[na:1.8.0_172]
at java.util.AbstractCollection.addAll(AbstractCollection.java:344) ~[na:1.8.0_172]
at org.hibernate.collection.internal.PersistentSet.endRead(PersistentSet.java:355) ~[hibernate-core-5.4.10.Final.jar:5.4.10.Final]
at org.hibernate.engine.loading.internal.CollectionLoadContext.endLoadingCollection(CollectionLoadContext.java:239) ~[hibernate-core-5.4.10.Final.jar:5.4.10.Final]
at org.hibernate.engine.loading.internal.CollectionLoadContext.endLoadingCollections(CollectionLoadContext.java:224) ~[hibernate-core-5.4.10.Final.jar:5.4.10.Final]
at org.hibernate.engine.loading.internal.CollectionLoadContext.endLoadingCollections(CollectionLoadContext.java:198) ~[hibernate-core-5.4.10.Final.jar:5.4.10.Final]
at org.hibernate.loader.plan.exec.process.internal.CollectionReferenceInitializerImpl.endLoading(CollectionReferenceInitializerImpl.java:154) ~[hibernate-core-5.4.10.Final.jar:5.4.10.Final]
at org.hibernate.loader.plan.exec.process.internal.AbstractRowReader.finishLoadingCollections(AbstractRowReader.java:267) ~[hibernate-core-5.4.10.Final.jar:5.4.10.Final]
at org.hibernate.loader.plan.exec.process.internal.AbstractRowReader.finishUp(AbstractRowReader.java:218) ~[hibernate-core-5.4.10.Final.jar:5.4.10.Final]
.
@GetMapping("/api/v1/stores/advance-search")
public List<Store> findStoresByFilter(
@RequestParam(required = false) String productName, @RequestParam(required = false) String branchName,
@RequestParam(required = false, defaultValue = "0") Integer minPrice,
@RequestParam(required = false, defaultValue = "999999") Integer maxPrice,
@RequestParam(required = false, defaultValue = "3000") Integer quantity) {
ProductParams productParams = ProductParams.builder().name(productName).minPrice(minPrice).maxPrice(maxPrice).build();
Branch branch = Branch.builder().name(branchName).build();
List<Store> stores = storeService.findStoresByFilter(productParams, branch, quantity);
System.out.println("Stores: " + stores);
return stores;
}
.
public List<Store> findStoresByFilter(ProductParams productParams, Branch branch, int quantity) {
System.out.println("productName: " + productParams.getName() + ", minPrice: " + productParams.getMinPrice() + ", maxPrice: "
+ productParams.getMaxPrice() + ", branchName: " + branch.getName() + ", " + quantity);
return storeRepository.searchStoresByFilter(productParams.getName(), branch.getName(),
productParams.getMinPrice(), productParams.getMaxPrice(), quantity);
}
.
@Query(nativeQuery = true,
value = "SELECT * " +
"FROM stores s " +
"INNER JOIN products p " +
"ON p.id = s.product_id " +
"INNER JOIN branches b " +
"ON b.id = s.branch_id " +
"WHERE (p.name LIKE CONCAT('%', :productName , '%') OR :productName IS NULL) " +
" AND (b.name LIKE CONCAT('%', :branchName , '%') OR :branchName IS NULL) " +
" AND (:minPrice <= p.price AND p.price <= :maxPrice) " +
" AND s.quantity <= :quantity " +
" ORDER BY p.name")
List<Store> searchStoresByFilter(@Param("productName") String productName, @Param("branchName") String branchName,
@Param("minPrice") double minPrice, @Param("maxPrice") double maxPrice, @Param("quantity") int quantity);
I am being flagged in my POJO classes that they have warnings about @Table and @JoinColumn from javax.persistence package
Cannot resolve table 'table_name'
in @Table and Cannot resolve column 'product_id'
Cannot resolve column 'branch_id'
in @JoinColumn
Thanks a lot for all your help
I am being flagged in my Entity classes that they have warnings about @Table from javax.persistence Cannot resolve table 'table_name' in @Table and Cannot resolve column 'product_id' Cannot resolve column 'branch_id' in @JoinColumn
That's the reason hibernate cannot actually map table, you need to fix mapping before anything else, so hibernate knows which table to use. Currently its looking for 'table_name' in sql which is not your store or product table. We do not know if your mappings are correct as your entity class code is not shared here, but it's likely that annotation or xml file has wrong mapping name from the error itself, ultimately crashing whole request.
Edit: kindly check if these libraries are included in your classpath : hibernate-annotations.jar lib/hibernate-comons-annotations.jar lib/ejb3-persistence.jar
Also I'd suggest you to use hibernate query language instead of native queries as they are much more extensible when you want to switch underlying database.
Root cause is, hibernate is database abstraction layer aka DBAL, whole purpose of this library is to build queries on behalf of your code and execute them. You are trying to use it as native sql wrapper, and sql queries would give result to hibernate but since mapping is wrong it cannot parse and store data in your Entities, while it's useful in some cases, hibernate itself provides much more roburst functionalities such as lazy loading, entity relations to name a few.
You can read full documentation here to use such functionalities. Getting started guide
I already found how to fixed Postman cannot finish this API and Frontend get an empty array.
I just add @ToString(exclude = "stores")
and @EqualsAndHashCode(exclude = "stores")
into Entity who have association as Many to Many .
The current code in entities are:
@Data
@ToString(exclude = "stores")
@EqualsAndHashCode(exclude = "stores")
@NoArgsConstructor
@AllArgsConstructor
@Entity
@Table(name = "products")
@Builder(toBuilder = true)
public class Product {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
@Column(nullable = false, length = 50)
private String name;
private String detail;
private double price;
@JsonIgnore
@OneToMany(mappedBy = "product")
private Set<Store> stores;
}
@Data
@ToString(exclude = "stores")
@EqualsAndHashCode(exclude = "stores")
@NoArgsConstructor
@AllArgsConstructor
@Entity
@Table(name = "branches")
@Builder(toBuilder = true)
public class Branch {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
@Column(nullable = false, length = 60)
private String name;
@JsonIgnore
@OneToMany(mappedBy = "branch")
private Set<Store> stores;
}
But I don't understand why it errors yet. Could you explain it ?
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.