'What is wrong with my native query in jpa?
I'm sending a very simple query to the database, but I'm getting an error. It feels like I'm missing something very simple. I guess it wouldn't allow me to create it because the word order is a keyword on the h2 db, so I put it in quotation marks within the table annotation.
@Query(value = "select * from `ORDER` o where o.basket_id= :basketId ", nativeQuery = true)
Optional<Order> getOrderByBasketId(Long basketId);
@Entity
@Getter
@Setter
@Table(name = "`ORDER`")
public class Order extends BaseExtendedModel{
private BigDecimal price;
@Enumerated(EnumType.STRING)
private OrderStatus orderStatus;
@OneToOne
private Customer customer;
@OneToOne(cascade = CascadeType.MERGE)
private Basket basket;
@OneToOne(cascade = CascadeType.ALL, mappedBy = "order")
private OrderAddress orderAddress;
}
{
"errorMessage": "could not prepare statement; SQL [select * from `ORDER` o where o.basket_id= ? ]; nested exception is org.hibernate.exception.SQLGrammarException: could not prepare statement"
}
Solution 1:[1]
The problem is easier to identidy when you have a look at the logs. You'll see an entry like this:
org.h2.jdbc.JdbcSQLSyntaxErrorException: Table "ORDER" not found; SQL statement:
So let's see what SQL statements are executed. So we add the following to application.properties
spring.jpa.show-sql=true
Assuming you let spring boot create your tables, you will see the following:
Hibernate: drop table if exists "order" CASCADE Hibernate: create table "order" ...
And when we hit the repository method we see
select * from `ORDER` o where o.name= ? [42102-200]
So why did it create the table in lowercase, even though we specified @Table(name = "`ORDER`")
?
The default for spring.jpa.hibernate.naming.physical-strategy
is org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy
, which
- replaces dots with underscores
- changes CamelCase to snake_case
- lower-cases table names.
But we want it to take the names we use in @Table
. That works when setting the property to spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
.
Yor native query will need the matching casing though.
Solution 2:[2]
You need to use index parameters
@Query(value = "select * from `ORDER` o where o.basket_id= ?1", nativeQuery = true)
Optional<Order> getOrderByBasketId(Long basketId);
or named parameters
@Query(value = "select * from `ORDER` o where o.basket_id= :basketId", nativeQuery = true)
Optional<Order> getOrderByBasketId(@Param("basketId") Long basketId);
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | peterulb |
Solution 2 | marc_s |