Spring MVC结合Spring Data JPA实现按条件查询和分页

下面是“Spring MVC结合Spring Data JPA实现按条件查询和分页”的完整攻略。

简介

Spring MVC结合Spring Data JPA可以实现按条件查询和分页,这对于实现Web应用程序中的高级搜索和结果分页非常有用。Spring MVC提供了有效的Web层,而Spring Data JPA则提供了持久层,两者结合可以快速搭建一个Web应用程序。本文将介绍如何使用Spring MVC和Spring Data JPA实现按条件查询和分页功能。

环境配置

首先确保你的电脑上已经安装好了JDK和Maven。然后,需要添加以下依赖项到Maven的pom.xml文件中。

<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-webmvc</artifactId>
  <version>5.2.9.RELEASE</version>
</dependency>
<dependency>
  <groupId>org.springframework.data</groupId>
  <artifactId>spring-data-jpa</artifactId>
  <version>2.3.5.RELEASE</version>
</dependency>

实现步骤

1. 指定实体类和仓库接口

首先定义一个实体类和对应的JpaRepository接口。本文以一个简单的用户实体类为例。

@Entity
@Table(name = "users")
public class User {

  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  private Long id;

  @Column(name = "username")
  private String username;

  @Column(name = "email")
  private String email;

  @Column(name = "password")
  private String password;

  // getters and setters
}
public interface UserRepository extends JpaRepository<User, Long> {

  List<User> findByUsernameContaining(String username, Pageable pageable);

  Long countByUsernameContaining(String username);
}

上面的仓库接口中定义了两个方法。第一个方法findByUsernameContaining用于可以按照用户名查询用户列表,并且可以传入Pageable参数实现结果分页。第二个方法countByUsernameContaining用于统计按条件查询用户列表的总数。

2. 配置JPA和数据源

在Spring Boot项目中,只需要在application.properties文件中配置相关信息即可使用JPA和数据源。下面是一个示例:

spring.datasource.url=jdbc:mysql://localhost:3306/test
spring.datasource.username=root
spring.datasource.password=password

spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=create
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect

根据实际情况修改以上配置信息。

3. 实现Controller

下面是一个基于Spring MVC的控制器,用于处理用户搜索请求。

@Controller
public class UserController {

  @Autowired
  private UserRepository userRepository;

  @GetMapping("/users")
  public String searchUsers(@RequestParam(value = "username", required = false, defaultValue = "") String username,
                                 @RequestParam(value = "page", required = false, defaultValue = "0") int page,
                                 Model model) {

    Page<User> result = userRepository.findByUsernameContaining(username,
            PageRequest.of(page, 10, Sort.by(Sort.Direction.ASC, "username")));
    model.addAttribute("users", result.getContent());
    model.addAttribute("currentPage", result.getNumber());
    model.addAttribute("totalPages", result.getTotalPages());
    model.addAttribute("totalItems", result.getTotalElements());
    model.addAttribute("keyword", username);

    return "userSearchResult";
  }
}

上述Controller的searchUsers方法会接收两个请求参数,一个是搜索用户的关键字,另一个是页码。然后调用UserRepository的findByUsernameContaining方法按照用户名查询用户,并返回分页结果。

4. 配置视图模板

最后,还需要配置一个视图模板,用于显示用户搜索结果。下面给出一个Thymeleaf的示例模板:

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
  <title>User Search Result</title>
  <meta charset="UTF-8"/>
</head>
<body>
  <h2>User Search Result</h2>
  <form method="get" th:action="@{/users}">
    <input type="text" th:name="username" th:value="${keyword}"/>
    <button type="submit">Search</button>
  </form>

  <table>
    <thead>
      <tr>
        <th>ID</th>
        <th>Username</th>
        <th>Email</th>
      </tr>
    </thead>
    <tbody>
      <tr th:each="user : ${users}">
        <td th:text="${user.id}"></td>
        <td th:text="${user.username}"></td>
        <td th:text="${user.email}"></td>
      </tr>
    </tbody>
  </table>

  <div>
    <span>Showing ${totalItems} users</span>
    <nav>
      <ul class="pagination">
        <li th:if="${currentPage > 0}">
          <a th:href="@{/users(page=0,keyword=${keyword})}" aria-label="First">
            <span aria-hidden="true">«</span>
          </a>
        </li>
        <li th:if="${currentPage > 0}">
          <a th:href="@{/users(page=${currentPage-1},keyword=${keyword})}" aria-label="Previous">
            <span aria-hidde n="true">‹</span>
          </a>
        </li>
        <li th:each="i : ${#numbers.sequence(0,totalPages-1)}" th:class="${currentPage == i} ? 'active' : '' ">
          <a th:href="@{/users(page=${i},keyword=${keyword})}" th:text="${i+1}">
          </a>
        </li>
        <li th:if="${currentPage < totalPages-1}">
          <a th:href="@{/users(page=${currentPage+1},keyword=${keyword})}" aria-label="Next">
            <span aria-hidde n="true">›</span>
          </a>
        </li>
        <li th:if="${currentPage < totalPages-1}">
          <a th:href="@{/users(page=${totalPages-1},keyword=${keyword})}" aria-label="Last">
            <span aria-hidden="true">»</span>
          </a>
        </li>
      </ul>
    </nav>
  </div>
</body>
</html>

上述Thymeleaf模板中显示了用户搜索结果以及分页导航。需要注意的是,其中涉及到的参数(如关键字、页码等)需要使用th:value,th:href等Thymeleaf属性进行动态渲染。

示例

下面给出两个简单的示例,一个是使用单元测试进行测试,另一个是使用Postman进行测试。

单元测试

下面是一个基于JUnit和Mockito的单元测试,用于测试UserController中的searchUsers方法。

@RunWith(MockitoJUnitRunner.class)
public class UserControllerUnitTest {

  @InjectMocks
  private UserController userController;

  @Mock
  private UserRepository userRepository;

  @Test
  public void should_returnUsers_when_searchUsers_givenKeyword() {
    // given
    List<User> userList = Arrays.asList(
            new User(1L, "Leo", "leo@example.com", "password1"),
            new User(2L, "Tom", "tom@example.com", "password2"));
    Page<User> result = new PageImpl<>(userList);
    when(userRepository.findByUsernameContaining(anyString(), any(Pageable.class)))
            .thenReturn(result);

    // when
    Model model = new ExtendedModelMap();
    String viewName = userController.searchUsers("leo", 0, model);

    // then
    assertEquals("userSearchResult", viewName);
    assertEquals(userList, model.getAttribute("users"));
    assertEquals(0, model.getAttribute("currentPage"));
    assertEquals(1, model.getAttribute("totalPages"));
    assertTrue((Boolean) model.getAttribute("totalPages") > 0);
    assertEquals(userList.size(), model.getAttribute("totalItems"));
    assertEquals("leo", model.getAttribute("keyword"));
  }
}

上述单元测试使用Mockito框架模拟了UserRepository中的findByUsernameContaining方法,并通过JUnit框架对UserController中的searchUsers方法进行代码覆盖率测试。测试结果应该返回包含用户数据的List对象。

Postman测试

另一个更为直观的测试方法是使用Postman进行接口测试。首先需要启动应用程序,然后在Postman中创建一个GET请求,请求地址为http://localhost:8080/users。下面是一个查询Leo用户的示例请求:

GET http://localhost:8080/users?username=Leo

应用程序将会返回包含Leo用户信息的JSON对象,以及分页信息(当前页码、总页数、总记录数):

{
  "users": [
    {
      "id": 1,
      "username": "Leo",
      "email": "leo@example.com",
      "password": "password1"
    }
  ],
  "currentPage": 0,
  "totalPages": 1,
  "totalItems": 1,
  "keyword": "Leo"
}

结论

本文介绍了如何使用Spring MVC和Spring Data JPA实现按条件查询和分页功能。结合Spring Boot的自动配置机制,开发Web应用程序变得更加简单、高效。希望这篇文章能够帮助到你。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Spring MVC结合Spring Data JPA实现按条件查询和分页 - Python技术站

(0)
上一篇 2023年5月20日
下一篇 2023年5月20日

相关文章

  • Springboot配置security basic path无效解决方案

    针对“Springboot配置security basic path无效解决方案”,以下是完整的攻略: 1. 问题描述 当我们在Spring Boot项目中将Spring Security集成进来时,有时候会发现配置的basic path无效,即虽然配置了basic path,但在请求时仍然需要登录验证,这种情况该怎么解决呢? 2. 解决方案 2.1 配置W…

    Java 2023年5月20日
    00
  • Mybatis中使用万能的Map传参实现

    现在我将给你详细讲解“Mybatis中使用万能的Map传参实现”完整攻略,让我们开始吧。 什么是Mybatis? MyBatis 是一个基于 Java 的持久层框架。通过配置 XML 映射文件或注解方式将 java 对象与 SQL 语句映射,是非常流行的 ORM 框架。Mybatis 提供了很多查询方法,我们可以使用 select、update、insert…

    Java 2023年5月20日
    00
  • Sprint Boot @PutMapping使用方法详解

    @PutMapping是Spring Boot中的一个注解,它用于将HTTP PUT请求映射到控制器方法上。在使用Spring Boot开发Web应用程序时,@PutMapping是非常重要的。本文将详细介绍@PutMapping的作用和使用方法,并提供两个示例说明。 @PutMapping的作用 @PutMapping的作用是将HTTP PUT请求映射到控…

    Java 2023年5月5日
    00
  • Mybatis Interceptor 拦截器的实现

    Mybatis Interceptor 拦截器是Mybatis框架使用的一种插件机制,可以拦截Sql语句执行的过程,对Sql进行加工或者做其他处理,比如增加动态SQL条件、查询性能优化等。以下是Mybatis Interceptor 拦截器的完整实现攻略: Mybatis Interceptor 拦截器的实现步骤 步骤1:定义自定义Interceptor类 …

    Java 2023年5月20日
    00
  • java连接mysql数据库乱码的解决方法

    以下是讲解“java连接mysql数据库乱码的解决方法”的完整攻略。 问题描述 在使用Java连接MySQL数据库时,有时会出现中文乱码的问题。如何解决这个问题呢?下面将会给出详细的解决方法。 解决方法 步骤一:指定编码方式 在连接MySQL数据库之前,需要指定编码方式。可以在连接数据库的URL中添加以下参数: jdbc:mysql://localhost/…

    Java 2023年5月19日
    00
  • MyBatis如何使用(一)

    先来简化一下这个任务,明确一下要求: 讲解MyBatis的使用方式 给出至少两个使用示例 以下是一个标准的Markdown文本,包含了需要的标题、代码块和示例。 MyBatis的使用方式 MyBatis 是一种 ORM 框架,它可以将 Java 类映射到数据库表,并提供了一组 API 用于执行 SQL 语句。 环境准备 首先,需要在项目中添加以下依赖: &l…

    Java 2023年5月20日
    00
  • Java泛型extends及super区别实例解析

    Java中的泛型可以指定一个类型参数,例如List,这表示这个List只能添加String类型的元素,否则编译器会报错。此外,泛型中还有一个重要的概念:泛型通配符。泛型通配符可以用来表示某个类的任意类型参数,例如List<?>,这表示这个List可以添加任意类型的元素。 当我们使用泛型通配符时,有时候需要限制可以添加的元素类型,这时可以使用ext…

    Java 2023年5月26日
    00
  • Java byte数组操纵方式代码实例解析

    Java byte数组操纵方式代码实例解析 简介 Java中的byte数组具有很多强大的操纵方式,使用这些操纵方式,我们可以灵活地操作byte数组中的每一个字节,完成各种各样的任务。 在本文中,我们将介绍几种Java中byte数组的操纵方式,并提供代码示例,帮助读者更好地理解和学习。 操作方式 1. 将byte数组转换为String 将byte数组转换为St…

    Java 2023年5月26日
    00
合作推广
合作推广
分享本页
返回顶部