当前位置: 移动技术网 > IT编程>开发语言>Java > Spring data JPA 多表联合分页查询 自定义实体类

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

2020年07月17日  | 移动技术网IT编程  | 我要评论

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

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网