Spring Boot / Hibernate在从MySQL数据库检索最近记录的数量时出现问题。

huangapple go评论61阅读模式
英文:

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 = &quot;user&quot;)
public class User {
    @Id
    @GeneratedValue
    @Type(type = &quot;uuid-char&quot;)
    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&lt;User, UUID&gt; {
    List&lt;User&gt; 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(&quot;silentsudo&quot;);
        silentSudo.setCreatedOn(getCreatedDate(5, Calendar.JULY, 2019));
        userRepository.save(silentSudo);
        Assertions.assertNotNull(silentSudo.getId());

        User randomUser = new User();
        randomUser.setName(&quot;random-user&quot;);
        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&lt;User&gt; 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 = &quot;select count(*) from User user where user.created_on &gt; date_add(now(), interval -1 month)&quot;

huangapple
  • 本文由 发表于 2020年10月1日 22:02:55
  • 转载请务必保留本文链接:https://go.coder-hub.com/64157041.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定