Spring Data JPA原生@Query方法与JUnit调用技术咨询
Let’s walk through your code and address common technical considerations, potential issues, and optimizations:
1. Critical Discrepancy Between Method Name and SQL Logic
Your method is named getMaxPriceAndDate, but your SQL uses order by cp.price ASC LIMIT 1 — this will return the lowest price in the date range, not the highest. To fix this for max price, change the sort direction to DESC:
select cp.price, cp.update_date from t_hotel_price cp where cp.hotel_id = ?1 and cp.update_date between ?2 and NOW() order by cp.price DESC LIMIT 1
Double-check this matches your intended business logic!
2. Improve Type Safety with Better Return Types
Using Object[] works, but it’s error-prone (you have to remember which index maps to price vs date). Instead, use one of these cleaner approaches:
Option 1: Create a DTO Class
Define a simple data transfer object:
public class PriceDateDto { private BigDecimal price; // Match the actual data type of your DB price column private LocalDateTime updateDate; // Constructor must match the order of columns in your SQL select statement public PriceDateDto(BigDecimal price, LocalDateTime updateDate) { this.price = price; this.updateDate = updateDate; } // Add getters for your fields public BigDecimal getPrice() { return price; } public LocalDateTime getUpdateDate() { return updateDate; } }
Then update your repository method to return this DTO (Spring Data will automatically map query results to the class):
@Query(value = "select cp.price, cp.update_date from t_hotel_price cp ...", nativeQuery = true) PriceDateDto getMaxPriceAndDate(Long hotelId, Date aggregationDate);
Option 2: Use Spring Data Projection
If you don’t want a full DTO, define a lightweight interface:
public interface PriceDateProjection { BigDecimal getPrice(); LocalDateTime getUpdateDate(); }
Update the repository method’s return type to PriceDateProjection — Spring Data will generate a dynamic implementation to map results to the interface methods.
3. Verify Parameter Consistency in Tests
In your JUnit test, you’re passing currency.getId() as the first argument to getMaxPriceAndDate, but the method expects a hotelId. Is this intentional? If currency.getId() doesn’t correspond to a valid hotel ID, this will return incorrect or empty results. Double-check that your parameter mapping aligns with your business logic.
4. Date Handling Best Practices
- Replace
DatewithLocalDateTime(Java 8+ Time API) for better timezone awareness and type safety. Update both your repository method signature and test code to useLocalDateTimeforaggregationDate. - The
NOW()function in SQL uses the database server’s timezone. Ensure this matches your application’s timezone configuration to avoid unexpected gaps or overlaps in your date range filter.
5. Repository Interface Fit
Since you’re extending PagingAndSortingRepository, you get built-in pagination and sorting methods, but your custom query doesn’t use these features. If you don’t need pagination/sorting capabilities for this repository, CrudRepository is a lighter alternative that still provides core CRUD operations.
内容的提问来源于stack exchange,提问作者Nunyet Calçada

