欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Spring data JPA 多表联合分页查询 自定义实体类

程序员文章站 2022-05-04 11:42:06
Spring data jpa 实现多表联合分页查询,自定义实体类接收返回对象集合1.定义返回结果实体类:2.DAO层方法编写3.定义Controller层方法调用工具类定义1.定义返回结果实体类:public class TestDTO{ private String name; // 名称 private String orgName; // 机构名称 private Date grantTime; // 授权时间 public TestDTO() {...

JPA 实现多表联合分页查询,自定义实体类接收返回对象集合

1.定义返回结果实体类:

public class TestDTO{

    private String name;    // 名称
    private String orgName; // 机构名称
    private Date grantTime;   // 授权时间

    public TestDTO() {  }

    public TestDTO(String name,String orgName,Date grantTime) {
        this.name=name;
        this.orgName=orgName;
        this.grantTime = grantTime;
    }      
    // 生成getter setter 方法;
}

2.DAO层方法编写

在dao层中编写两个方法,一个查询集合的分页数据;一个查询返回的总条数;

  public interface TestDao extends JpaRepository<BaseEntity,String> {
	/**
	 * 查询分页列表
	 * @param id	查询条件
	 * @param start	分页起始位
	 * @param size	终止位
	 * @return
	 */
	@Query((value="select t1.name,t2.orgName,t2.grantTime "+
				"from table1 t1 
				left join t2 on t1.id=t2.id "+
				"where t1.id=?1 limit ?2,?3 ",
		nativeQuery=true)
	public List<Object[]> getList(String id, @Param("start") long start, @Param("size") int size);
	
	/**
	  * 查询分页列表
	  * @param id 查询条件
	  * @param start 分页起始位
	  * @param size 终止位
	  * @return
	  */
	 @Query((value="select count(*) from 
	  		"(select t1.name,t2.orgName,t2.grantTime "+
	   	 	"from table1 t1 
	   		"left join t2 on t1.id=t2.id "+
	    		"where t1.id=?1 ) as testTable",
	  nativeQuery=true)
	  public Integer getCountNum(String id);
}

查询方法的返回集合须是List<Object[]>

3.定义Controller层方法调用

@RequestMapping("/grantList")
    public Object queryUserByParam( @RequestParam(defaultValue = "1") int pageNumber,
                                              @RequestParam(defaultValue = "10") int pageSize,
                                            
                                              @RequestParam(value="") String id) {

	// 分页- 根据入参计算起始位置,jpa分页开始页数默认从0开始,这里-1
PageRequest pageRequest = PageRequest.of(pageNum-1, pageSize);
	
	// 查询总条数
	int totalNum = testDao.getCountNum(id);
	// 查询集合
	List<Object[]> objList = testDao.getList(id,pageRequest.getOffset(),pageRequest.getPageSize());
	
	// 转换为实体类的集合
List<TestDTO> retList = EntityUtils.castEntity(objList, TestDTO.class,new TestDTO());

	// 定义分页
	PageDTO<TestDTO> dto = null;
	// 总条数
	dto.setTotal(totalNum);
	// 封装数据
	if (!retList.isEmpty()) {
	    for(TestDTO tDto:retList){
	        dto.addItem(tDto);
	    }
	}
	// 返回
	return dto.toMap();
 }

4.工具类定义

/**
 * Spring Data JPA映射自定义实体类 工具类
 * 转换实体
 */
public class EntityUtils {

    // 日志
    private final static Logger logger = LoggerFactory.getLogger(EntityUtils.class);
    /**
     * 反射转换
     * @param list
     * @param clazz
     * @param model
     * @param <T>
     * @return
     */
    public static <T> List<T> castEntity(List<Object[]> list, Class<T> clazz, Object model) {
        List<T> returnList = new ArrayList<T>();
        if (list.isEmpty()) {
            return returnList;
        }
        //获取每个数组集合的元素个数
        Object[] co = list.get(0);
        //获取当前实体类的属性名、属性值、属性类别
        List<Map> attributeInfoList = getFiledsInfo(model);
        //创建属性类别数组
        Class[] c2 = new Class[attributeInfoList.size()];
        //如果数组集合元素个数与实体类属性个数不一致则发生错误
        if (attributeInfoList.size() != co.length) {
            return returnList;
        }
        //确定构造方法
        for (int i = 0; i < attributeInfoList.size(); i++) {
            c2[i] = (Class) attributeInfoList.get(i).get("type");
        }
        try {
            for (Object[] o : list) {
                Constructor<T> constructor = clazz.getConstructor(c2);
                returnList.add(constructor.newInstance(o));
            }
        } catch (Exception ex) {
            logger.error("实体数据转化为实体类发生异常:异常信息:{}", ex.getMessage());
            return returnList;
        }
        return returnList;
    }

    /**
     * * 获取属性类型(type),属性名(name),属性值(value)的map组成的list
     * @param model 实体类
     *  @return list集合
     */
    private static List<Map> getFiledsInfo(Object model) {
        Field[] fields = model.getClass().getDeclaredFields();
        List<Map> list = new ArrayList(fields.length);
        Map infoMap = null;
        for (int i = 0; i < fields.length; i++) {
            infoMap = new HashMap(3);
            infoMap.put("type", fields[i].getType());
            infoMap.put("name", fields[i].getName());
            infoMap.put("value", getFieldValueByName(fields[i].getName(), model));
            list.add(infoMap);
        }
        return list;
    }
    /**
     * 根据属性名获取属性值
      */
    private static Object getFieldValueByName(String fieldName, Object modle) {
        try {
            String firstLetter = fieldName.substring(0, 1).toUpperCase();
            String getter = "get" + firstLetter + fieldName.substring(1);
            Method method = modle.getClass().getMethod(getter, new Class[]{});
            Object value = method.invoke(modle, new Object[]{});
            return value;
        } catch (Exception e) {
            return null;
        }
    }

/**
 * 分页DTO返回 格式化类
 * @param <T>
 */
public class PageDTO <T> {
    long total;
    List<T> items = new ArrayList<>();

    String totalName;
    String dataName ;
    public PageDTO(String totalName,String dataName) {
        this.total = total;
        this.totalName = totalName;
        this.dataName = dataName;
    }

    public void addItem(T t){
        this.items.add(t);
    }

    public long getTotal() {
        return total;
    }

    public void setTotal(long total) {
        this.total = total;
    }

    public List<T> getItems() {
        return items;
    }

    public void setItems(List<T> items) {
        this.items = items;
    }

    public Map<String,Object> toMap(){
        Map<String,Object> map = new HashMap<>();
        map.put(totalName,total);
        map.put(dataName,this.items);
        return map;
    }
}

实体类与查询的sql列的字段顺序要保持一直。

本文地址:https://blog.csdn.net/weixin_43494358/article/details/107348243