I am using Spring Boot and Spring JPA. I have a repository class with custom @Query
methods.
public interface MarketForceRepository extends CrudRepository<MarketForceComment, Integer> {
@Query("SELECT c FROM MarketForceComment c WHERE c.property.id = ?1 and c.commentDate >= '?1' AND c.commentDate <= '?2'")
List<MarketForceComment> getByPropAndDate(Integer propID, LocalDate start, LocalDate end);
@Query("SELECT c FROM MarketForceComment c WHERE c.property.id IN ?1 and c.commentDate >= '?2' AND c.commentDate <= '?3'")
List<MarketForceComment> getByPropsAndDates(List<Integer> propIDs, LocalDate start, LocalDate end);
}
The MarketForceComment
class follows (in part):
@Table(name = "MarketForceComment", schema = "dmb")
@Entity
public class MarketForceComment {
@ManyToOne
@JoinColumn(name = "PropertyID")
private Property property;
@Column(name = "CommentDate")
private LocalDate commentDate;
@Column(name = "Level")
private int level;
@Column(name = "Subject")
private String subject;
@Column(name = "Details", columnDefinition = "text")
private String details;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "ID")
private Integer id;
.... }
Whenever I attempt to run my query method:
@Override
public List<CommentDTO> getCommentsByStore(int storeID, LocalDate date) {
List<CommentDTO> dtoList = new ArrayList<>();
marketRepo.getByPropAndDate(storeID, date.plusMonths(1), date)
.forEach(c -> dtoList.add(mapper.map(c, CommentDTO.class)));
guestRepo.getByPropAndDate(storeID, date.plusMonths(1).atStartOfDay(), date.atStartOfDay())
.forEach(c -> dtoList.add(mapper.map(c, CommentDTO.class)));
return dtoList;
}
I receive the following error:
com.microsoft.sqlserver.jdbc.SQLServerException: Conversion failed when converting date and/or time from character string.
I am a bit perplexed. It appears to be a format issue (the DBMS wants a 'yyyy-MM-dd' or similar format), yet I thought Java's LocalDate would be expressed/converted into a format that could be parsed by database system.
Any advice would be appreciated. Thanks.
EDIT:
For reference, the underlying fault was the order of the parameters (?1, ?2, ?3):
public interface MarketForceRepository extends CrudRepository<MarketForceComment, Integer> {
@Query("SELECT c FROM MarketForceComment c WHERE c.property.id = ?1 and c.commentDate >= ?2 AND c.commentDate <= ?3")
List<MarketForceComment> getByPropAndDate(Integer propID, LocalDate start, LocalDate end);
@Query("SELECT c FROM MarketForceComment c WHERE c.property.id IN ?1 and c.commentDate >= ?2 AND c.commentDate <= ?3")
List<MarketForceComment> getByPropsAndDates(List<Integer> propIDs, LocalDate start, LocalDate end);
}
Please have a look at: How to persist JSR-310 types with Spring Data JPA?
Depending on the framework versions you use, you have to add additional configuration to your project to use JSR-310 types like LocalDate in your entities.
If you are using JPA version lower than 2.2, it doesn't directly support Java8 LocalDate & LocalTime conversion from SqlDate, as it was released before Java8. You will have to write your custom date converter by implementing JPA
AttributeConverter
interface. Then either you canautoApply
it for all entity classes or you can selectively annotate it to LocalDate entity field.With
autoApply = true
JPA will automatically associate this converter whereaever Entity fields are LocalDate.Or if you choose
autoApply = false
, you will have to associate converter class via annotation with the field.Refer JPA 2.2 release spec