英文:
Problem with Spring Boot/Hibernate while retrieving the number of recent records from MySQL database
问题
我在userRepository中使用以下查询来获取最近一个月内在MySQL中创建的记录:
@Query("select count(*) from User user where user.created_on > date_add(now(), interval -1 month)")
但是我遇到了以下错误:
antlr.MismatchedTokenException: expecting CLOSE, found 'month'
at antlr.Parser.match(Parser.java:211) ~[antlr-2.7.7.jar:na]
antlr.MismatchedTokenException: expecting EOF, found ')'
at antlr.Parser.match(Parser.java:211) ~[antlr-2.7.7.jar:na]
我该如何解决这个问题?
英文:
I am using the following query in the userRepository to fetch the recent records which is created in the last month from MySQL
@Query("select count(*) from User user where user.created_on > date_add(now(), interval -1 month)")
But I am getting the following errors.
antlr.MismatchedTokenException: expecting CLOSE, found 'month'
at antlr.Parser.match(Parser.java:211) ~[antlr-2.7.7.jar:na]
antlr.MismatchedTokenException: expecting EOF, found ')'
at antlr.Parser.match(Parser.java:211) ~[antlr-2.7.7.jar:na]
How can I resolve this issue?
答案1
得分: 1
以下是您提供的内容的翻译部分:
嗨,在这种情况下,我将不建议使用 JPQL/SQL 查询。我是这样做的:创建存储库并使用方法 findAllByCreatedOnBetween
,将当前月份和上个月份作为日期对象传递,因此您基本上在选择给定日期之间的所有行。
下面是 Hibernate 生成的 SQL:
生成的 SQL:
select user0_.id as id1_20_, user0_.created_on as created_2_20_, user0_.name as name3_20_ from user user0_ where user0_.created_on between ? and ?
实体类 User.java
:
import org.hibernate.annotations.Type;
import javax.persistence.*;
import java.util.Date;
import java.util.UUID;
@Entity
@Table(name = "user")
public class User {
@Id
@GeneratedValue
@Type(type = "uuid-char")
private UUID id;
private String name;
@Temporal(value = TemporalType.DATE)
private Date createdOn;
public UUID getId() {
return id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Date getCreatedOn() {
return createdOn;
}
public void setCreatedOn(Date createdOn) {
this.createdOn = createdOn;
}
}
存储库:
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import java.util.Date;
import java.util.List;
import java.util.UUID;
@Repository
public interface UserRepository extends JpaRepository<User, UUID> {
List<User> findAllByCreatedOnBetween(Date lastMonth, Date currentMonth);
}
单元测试:
import in.silentsudo.hibernatetips.TestApplication;
import in.silentsudo.hibernatetips.domain.User;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.transaction.annotation.Transactional;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
@ExtendWith(SpringExtension.class)
@Transactional
@SpringBootTest(classes = TestApplication.class)
class UserCreatedInLastMonth {
@Autowired
private UserRepository userRepository;
@Test
void testUserCreatedLastMonth() {
User silentSudo = new User();
silentSudo.setName("silentsudo");
silentSudo.setCreatedOn(getCreatedDate(5, Calendar.JULY, 2019));
userRepository.save(silentSudo);
Assertions.assertNotNull(silentSudo.getId());
User randomUser = new User();
randomUser.setName("random-user");
randomUser.setCreatedOn(getCreatedDate(1, Calendar.OCTOBER, 2020));
userRepository.save(randomUser);
Assertions.assertNotNull(randomUser.getId());
//Current Calendar
Calendar currentCalendar = Calendar.getInstance();
Date today = currentCalendar.getTime();
//A month before
currentCalendar.add(Calendar.MONTH, -1);
Date monthBefore = currentCalendar.getTime();
Assertions.assertTrue(today.after(monthBefore));
List<User> allUserInLastMonth = userRepository.findAllByCreatedOnBetween(monthBefore, today);
Assertions.assertEquals(1, allUserInLastMonth.size());
}
private Date getCreatedDate(int day, int month, int year) {
Calendar createdDate = Calendar.getInstance();
createdDate.set(Calendar.DAY_OF_MONTH, day);
createdDate.set(Calendar.MONTH, month);
createdDate.set(Calendar.YEAR, year);
return createdDate.getTime();
}
}
英文:
Hi i will go against using jpql/sql query in this case. This is how i have done it. Create repository and use method findAllByCreatedOnBetween
pass current and last month as date object, so you are basically selecting all rows between given dates.
Here is the sql generated by hibernate
Generated SQL:
select user0_.id as id1_20_, user0_.created_on as created_2_20_, user0_.name as name3_20_ from user user0_ where user0_.created_on between ? and ?
Entity Class User.java
import org.hibernate.annotations.Type;
import javax.persistence.*;
import java.util.Date;
import java.util.UUID;
@Entity
@Table(name = "user")
public class User {
@Id
@GeneratedValue
@Type(type = "uuid-char")
private UUID id;
private String name;
@Temporal(value = TemporalType.DATE)
private Date createdOn;
public UUID getId() {
return id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Date getCreatedOn() {
return createdOn;
}
public void setCreatedOn(Date createdOn) {
this.createdOn = createdOn;
}
}
Repository
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import java.util.Date;
import java.util.List;
import java.util.UUID;
@Repository
public interface UserRepository extends JpaRepository<User, UUID> {
List<User> findAllByCreatedOnBetween(Date lastMonth, Date currentMonth);
}
Unit Test
import in.silentsudo.hibernatetips.TestApplication;
import in.silentsudo.hibernatetips.domain.User;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.transaction.annotation.Transactional;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
@ExtendWith(SpringExtension.class)
@Transactional
@SpringBootTest(classes = TestApplication.class)
class UserCreatedInLastMonth {
@Autowired
private UserRepository userRepository;
@Test
void testUserCreatedLastMonth() {
User silentSudo = new User();
silentSudo.setName("silentsudo");
silentSudo.setCreatedOn(getCreatedDate(5, Calendar.JULY, 2019));
userRepository.save(silentSudo);
Assertions.assertNotNull(silentSudo.getId());
User randomUser = new User();
randomUser.setName("random-user");
randomUser.setCreatedOn(getCreatedDate(1, Calendar.OCTOBER, 2020));
userRepository.save(randomUser);
Assertions.assertNotNull(randomUser.getId());
//Current Calendar
Calendar currentCalendar = Calendar.getInstance();
Date today = currentCalendar.getTime();
//A month before
currentCalendar.add(Calendar.MONTH, -1);
Date monthBefore = currentCalendar.getTime();
Assertions.assertTrue(today.after(monthBefore));
List<User> allUserInLastMonth = userRepository.findAllByCreatedOnBetween(monthBefore, today);
Assertions.assertEquals(1, allUserInLastMonth.size());
}
private Date getCreatedDate(int day, int month, int year) {
Calendar createdDate = Calendar.getInstance();
createdDate.set(Calendar.DAY_OF_MONTH, day);
createdDate.set(Calendar.MONTH, month);
createdDate.set(Calendar.YEAR, year);
return createdDate.getTime();
}
}
答案2
得分: 0
你正在使用JPQL,因为它在@Query注解中默认使用。
通过以下方式启用原生SQL查询:
@Query(nativeQuery = true, value = "select count(*) from User user where user.created_on > date_add(now(), interval -1 month)")
英文:
You are using JPQL, since it is used by default with @Query annotation.
Enable native SQL query with:
@Query(nativeQuery = true, value = "select count(*) from User user where user.created_on > date_add(now(), interval -1 month)"
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论