本文所属【知识林】:http://www.zslin.com/web/article/detail/18

在网站系统的开发过程中经常会用到排序操作,下面就我个人的理解介绍一下使用强大的JPA是如何进行排序的。

基础搭建

  • pom.xml
<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>1.4.0.RELEASE</version>
    <relativePath/>
</parent>

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
    </dependency>
</dependencies>
  • application.properties
server.port=80

# Hibernate 相关配置

## 自动扫描的包前缀
entitymanager.packagesToScan= com.zslin

## 数据库连接
spring.datasource.url=jdbc:mysql://localhost:3306/study05?\
  useUnicode=true&characterEncoding=utf-8&useSSL=true&autoReconnect=true

## 用户名
spring.datasource.username=root

## 密码
spring.datasource.password=123

## 数据库驱动
spring.datasource.driver-class-name=com.mysql.jdbc.Driver

## 建表方式
spring.jpa.properties.hibernate.hbm2ddl.auto=update

# 方言
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5Dialect
  • 项目入口
package com.zslin;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

/**
 * Created by 钟述林 393156105@qq.com on 2016/10/21 10:54.
 */
@SpringBootApplication
public class RootApplication {

    public static void main(String [] args) {
        SpringApplication.run(RootApplication.class, args);
    }
}
  • 数据实体对象
package com.zslin.model;

import javax.persistence.*;

/**
 *
 * Created by 钟述林 393156105@qq.com on 2016/10/21 10:55.
 */
@Entity
@Table(name = "t_user")
public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Integer id;

    @Column(name = "user_name")
    private String userName;

    private String password;

    @Column(name = "nick_name")
    private String nickName;

    private String email;

    ……省去get和set方法……
}
  • 数据接口
package com.zslin.service;

import com.zslin.model.User;
import org.springframework.data.jpa.repository.JpaRepository;

/**
 * Created by 钟述林 393156105@qq.com on 2016/10/21 10:56.
 */
public interface IUserService extends JpaRepository<User, Integer> {
}

以上这些配置在前面很多测试例子中都已描述过,在此不再做过多赘述。

数据准备

package com.zslin;

import com.zslin.model.User;
import com.zslin.service.IUserService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

/**
 * Created by 钟述林 393156105@qq.com on 2016/10/21 11:08.
 */
@SpringBootTest
@RunWith(SpringRunner.class)
public class UserInitTest {

    @Autowired
    private IUserService userService;

    @Test
    public void initTest() {
        for(int i=1; i<=10; i++) {
            User u = new User();
            u.setEmail("email"+i+"@domain.com");
            u.setPassword("pwd"+i);
            u.setUserName("user"+i);
            u.setNickName("nickname"+i);
            userService.save(u);
        }
    }
}

先初始化10条数据到数据库中,方便后面做排序和分布的操作。

排序

  • 基本测试
@Test
public void testPage() {
    Sort sort = new Sort(Sort.Direction.DESC, "id");
    List<User> list = userService.findAll(sort);
    for(User u : list) {
        System.out.println(u.getUserName());
    }
}

注意: 当继承JpaRepository之后,IUserService拥有了几个findAll()的重载方法,其中一个可以传Sort对象,该方法则是排序的方法。

Sort sort = new Sort(Sort.Direction.DESC, "id");:表示通过id进行降序排序,将DESC换成ASC则表示升序,将id换成其他User对象的属性后,则通过其他字段排序。

  • 单排序封装

为更好的使用排序功能,可将Sort进行二次封装以解决代码重用的问题。

public class SortTools {

    public static Sort basicSort() {
        return basicSort("desc", "id");
    }

    public static Sort basicSort(String orderType, String orderField) {
        Sort sort = new Sort(Sort.Direction.fromString(orderType), orderField);
        return sort;
    }
}

这样封装的好处是:不用每次进行排序时都new个Sort对象作为参数传入;比较方便灵活的根据自己需求传入要排序的方式与字段。

封装后的测试方法:

@Test
public void testSort2() {
    List<User> list = userService.findAll(SortTools.basicSort());
    for(User u : list) {
        System.out.println(u.getUserName());
    }
}

@Test
public void testSort3() {
    List<User> list = userService.findAll(SortTools.basicSort("desc", "userName"));
    for(User u : list) {
        System.out.println(u.getUserName());
    }
}
  • 多排序封装

上面的封装方法只能满足单一排序的需求,如果有多条件排序就无法满足了,下面改进一下封装:

  1. 创建Sort的DTO对象
package com.zslin.tools;

/**
 * Created by 钟述林 393156105@qq.com on 2016/10/21 11:41.
 */
public class SortDto {

    //排序方式
    private String orderType;

    //排序字段
    private String orderField;

    public String getOrderField() {
        return orderField;
    }

    public void setOrderField(String orderField) {
        this.orderField = orderField;
    }

    public String getOrderType() {
        return orderType;
    }

    public void setOrderType(String orderType) {
        this.orderType = orderType;
    }

    public SortDto(String orderType, String orderField) {
        this.orderType = orderType;
        this.orderField = orderField;
    }

    //默认为DESC排序
    public SortDto(String orderField) {
        this.orderField = orderField;
        this.orderType = "desc";
    }
}
  1. 增加basicSort方法
public static Sort basicSort(SortDto... dtos) {
    Sort result = null;
    for(int i=0; i<dtos.length; i++) {
        SortDto dto = dtos[i];
        if(result == null) {
            result = new Sort(Sort.Direction.fromString(dto.getOrderType()), dto.getOrderField());
        } else {
            result = result.and(new Sort(Sort.Direction.fromString(dto.getOrderType()), dto.getOrderField()));
        }
    }
    return result;
}
  1. 测试方法
@Test
public void testSort4() {
    List<User> list = userService.findAll(SortTools.basicSort(new SortDto("desc", "userName"), new SortDto("id")));
    for(User u : list) {
        System.out.println(u.getId()+"===="+u.getUserName());
    }
}

上面这个测试方法就是首先按userName的降序排,再按id的降序排,在此basicSort方法中可以传任意个new SortDto()

示例代码:https://github.com/zsl131/spring-boot-test/tree/master/study08

本文所属【知识林】:http://www.zslin.com/web/article/detail/18
文章点评共:4 条
点评内容: 提交点评

12-16 点评:嘻嘻

07-25 点评:代码写的墨迹极了

07-20 点评:可以哦

06-02 点评:可以