实施日期范围搜索

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

Implement search with date range

问题

Here are the translated portions of your content:

要实现使用Spring Boot的日期范围搜索。我尝试了这个:

端点:

@GetMapping(value = "/users", produces = MediaType.APPLICATION_JSON_VALUE)
public Page<UsersResource> getUsersBySearchSpecification(@Valid UserSearchParams params, Pageable pageable)
{
    Page<UsersResource> list = userService.getUsersBySpecification(params, pageable);
    return list;
}

UserSearchParams:

@Getter
@Setter
public class UserSearchParams {

    private String param1;

    private Integer param2;

    private List<String> param3;

    @DateTimeFormat(iso = DATE_TIME) 
    LocalDateTime startDate;

    private OffsetDateTime createdAt;
}

搜索功能:

public Page<Users> getUsersBySpecification(UserSearchParams params, Pageable pageable)
{
    Specification<Users> spec = (root, query, cb) -> {
        List<Predicate> predicates = new ArrayList<>();
        if (params.getCreatedAt() != null) {
            predicates.add(cb.greaterThan(root.get("createdAt"), params.getCreatedAt()));
        }
        if (params.getCreatedAt() != null) {
            predicates.add(cb.lessThan(root.get("createdAt"), params.getCreatedAt()));
        }
        return cb.and(predicates.toArray(new Predicate[predicates.size()]));
    };

    return userRepository.findAll(spec, pageable);
}

这个搜索功能不起作用。createdAt 应该使用什么数据类型?OffsetDateTime 还是 LocalDateTime 更好?

我应该手动解析值 2023-05-02T04:57:19.83795Z 还是可以依赖Spring Boot来解析日期?

这段代码是否正确实现:

if (params.getCreatedAt() != null) {
    predicates.add(cb.greaterThan(root.get("createdAt"), params.getCreatedAt()));
}
if (params.getCreatedAt() != null) {
    predicates.add(cb.lessThan(root.get("createdAt"), params.getCreatedAt()));
}

还有更好的方法来选择日期范围吗?

英文:

I want to implement Date range search using Spring Boot. I tried this:

url: localhost:8080/users/users?page=0&amp;size=3&amp;createdAt=2023-05-02T04:57:19.83795Z

Endpoint:

    @GetMapping(value = &quot;/users&quot;, produces = MediaType.APPLICATION_JSON_VALUE)
    public Page&lt;UsersResource&gt; getUsersBySearchSpecification(@Valid UserSearchParams params, Pageable pageable)
    {
        Page&lt;UsersResource&gt; list = userService.getUsersBySpecification(params, pageable);
        return list;
    }

UserSearchParams:

@Getter
@Setter
public class UserSearchParams {

    private String param1;

    private Integer param2;

    private List&lt;String&gt; param3;

    @DateTimeFormat(iso = DATE_TIME) 
    LocalDateTime startDate;

    private OffsetDateTime createdAt;
}

Search functionality:

    public Page&lt;Users&gt; getUsersBySpecification(UserSearchParams params, Pageable pageable)
    {
        Specification&lt;Users&gt; spec = (root, query, cb) -&gt; {
            List&lt;Predicate&gt; predicates = new ArrayList&lt;&gt;();
            if (params.getCreatedAt() != null) {
                predicates.add(cb.greaterThan(root.get(&quot;createdAt&quot;), params.getCreatedAt()));
            }
            if (params.getCreatedAt() != null) {
                predicates.add(cb.lessThan(root.get(&quot;createdAt&quot;), params.getCreatedAt()));
            }
            return cb.and(predicates.toArray(new Predicate[predicates.size()]));
        };

    return userRepository.findAll(spec, pageable);
}

The search functionality is not working. What data type should I use for createdAt? OffsetDateTime or LocalDateTime is better alternative?

Should I manually parse the value 2023-05-02T04:57:19.83795Z or I can rely on Spring Boot to parse the date?.

Is this code properly implemented:

        if (params.getCreatedAt() != null) {
            predicates.add(cb.greaterThan(root.get(&quot;createdAt&quot;), params.getCreatedAt()));
        }
        if (params.getCreatedAt() != null) {
            predicates.add(cb.lessThan(root.get(&quot;createdAt&quot;), params.getCreatedAt()));
        }

Or there is better way to to have this range select?

答案1

得分: 4

Let me answer step by step based on the experience that I have (multiple different enterprise projects). Additional note: I was mostly working with PostgreSQL as a database.

  • 通常使用LocalDateTime。因为它更方便,没有时区信息。对于数据库,通常使用timestamp作为适当的列类型。

  • Spring Boot能够解析请求参数到LocalDateTime类型,无需显式的自定义配置实现。这是一个LocalDateTime类型的请求示例:

    • https://localhost:8080/my/endpoint?startDate=2023-01-01T00:30:00.000&amp;endDate=2023-12-31T23:30:00.000
    • https://localhost:8080/my/endpoint?startDate=2023-01-01T00%3A30%3A00.000&amp;endDate=2023-12-31T23%3A30%3A00.000(HTML解码)

    这是适当的控制器代码:

    @GetMapping(value = &quot;/my/endpoint&quot;)
    public void myMethod(
            @RequestParam(name = &quot;startDate&quot;) @DateTimeFormat(iso = DATE_TIME) LocalDateTime startDate,
            @RequestParam(name = &quot;endDate&quot;) @DateTimeFormat(iso = DATE_TIME) LocalDateTime endDate) {
        return doSearch(startDate, endDate);
    }

但要小心旧版本的Spring。根据我的经验,从Spring Boot 2.2.X版本开始应该可以工作。***关键是要使用高于2.1版本的JPA实现,因为在2.1版本中使用LocalDateTime不太方便。***简而言之,请使用现代版本。

更多信息可以在这里找到。

英文:

Let me answer step by ste based on the experience that I have (multiple different enterprise projects). Additional note: I was mostly working with PostgreSQL as a database.

  • Usually LocalDateTime is used. Because it's a bit more convenient to work with an it has no time-zone info. For databases usually timestamp is the appropriate column type.

  • Spring Boot is able to parse request parameters to LocalDateTime type without explicit custom config implementations. Here is an example of request for LocalDateTime type:

    • https://localhost:8080/my/endpoint?startDate=2023-01-01T00:30:00.000&amp;endDate=2023-12-31T23:30:00.000
    • https://localhost:8080/my/endpoint?startDate=2023-01-01T00%3A30%3A00.000&amp;endDate=2023-12-31T23%3A30%3A00.000 (html decoded)

    Here is the appropriate controller code:

    @GetMapping(value = &quot;/my/endpoint&quot;)
    public void myMethod(
            @RequestParam(name = &quot;startDate&quot;) @DateTimeFormat(iso = DATE_TIME) LocalDateTime startDate,
            @RequestParam(name = &quot;endDate&quot;) @DateTimeFormat(iso = DATE_TIME) LocalDateTime endDate) {
        return doSearch(startDate, endDate);
    }

But be careful with old Spring versions. From my experience, it should work since Spring Boot 2.2.X. The idea is to have an implementation of JPA higher than 2.1 version, because in 2.1 version there is no convenient using of LocalDateTime. Simply put, use modern versions.

A bit more information can be found here.

huangapple
  • 本文由 发表于 2023年5月7日 20:18:59
  • 转载请务必保留本文链接:https://go.coder-hub.com/76193883.html
匿名

发表评论

匿名网友

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

确定