2、可能是目前最好理解的spring-data-jpa对象关联多表查询+分页

1、确定两个表之间的关系

1.1、r_menu 菜单表

关系:菜单表和报表是一对多关系

1.2、r_report 报表 

关系:报表和菜单表是多对一关系

2、配置出实体类和数据库表的关系映射

2.1、菜单表对象实体:

package com.tc.report.dataobject;


import javax.persistence.Entity;

import javax.persistence.Id;

import javax.persistence.Table;


import lombok.Data;


@Data

@Entity

@Table(name="r_menu")

public class Menu {


    @Id

    private String menuId;

    private String menuName;

    private String menuIcon;

    /* 没有权限的菜单图标 */

    private String menuNicon;

    private Integer status;

    private String menuPath;

}

2.2、报表对象实体:

package com.tc.report.dataobject;


import java.util.Date;


import javax.persistence.Entity;

import javax.persistence.Id;

import javax.persistence.JoinColumn;

import javax.persistence.ManyToOne;

import javax.persistence.Table;


import lombok.Data;

import lombok.ToString;


import com.fasterxml.jackson.annotation.JsonFormat;


@Data

@ToString

@Entity

@Table(name="r_report")

public class Report {



    @Id

    private String reportId;

    private String reportName;

    private String reportPath;

    private String reportFileName;

    /* 菜单id外键  */

    private String menuId;

    /* 0:表示启用,1:表示禁用 */

    private Integer status;

    @JsonFormat(pattern="yyyy-MM-dd HH:mm:ss",timezone="GMT+8")

    private Date createTime;

    @JsonFormat(pattern="yyyy-MM-dd HH:mm:ss",timezone="GMT+8")

    private Date updateTime;

     

    /**

     * 多对一关系 

     *   targetEntityClass:指定一的一方实体类字节码。

     *   cascade:指定要使用的级联操作 。

     *   fetch:指定是否采用延迟加载 。

     *   optional:关联是否可选。如果设置为false,则必须始终存在非空关系。

     */

    @ManyToOne(targetEntity=Menu.class)

    /**

     * name:指定外键字段的名称。( 多的一方从表Report的menuId )

     * referencedColumnName:指定引用主表的主键字段名称。( 少的一方主表menu的menuId )

     * unique:是否唯一。默认值不唯一 。

     * nullable:是否允许为空。默认值允许。 

     * insertable:是否允许插入。默认值允许。

     * updatable:是否允许更新。默认值允许。 

     * columnDefinition:列的定义信息。

     */

    @JoinColumn(name="menuId",referencedColumnName="menuId",insertable=false,updatable=false)

    private Menu menu;

}

2.3、Specification条件分页关联查询:

2.3.1、vo层:

@Data
public class ReportVo extends Report{
    private Integer page = 1;   
    private Integer limit = 10;
    private String menuName;
}

2.3.2、dao层:

public interface ReportRepository extends JpaRepository<Report, String>,JpaSpecificationExecutor<Report>{

}

2.3.3、service层:

public PageResult loadAllReports(ReportVo reportVo) {

    // 分页设置

    Sort sort = new Sort(Sort.Direction.DESC, "updateTime");

    PageRequest pageRequest = PageRequest.of(reportVo.getPage()-1, reportVo.getLimit(),sort);

    // 构建动态查询

    Specification<Report> specification = createSpecification(reportVo);

    Page<Report> page = reportRepository.findAll(specification, pageRequest);

    return new PageResult(page.getTotalElements(), page.getContent());

}



/**

 * 动态条件构建 sql查询

 * 

 * @param ReportVo

 * @return

 */

@SuppressWarnings("serial")

private Specification<Report> createSpecification(ReportVo reportVo) {

    return new Specification<Report>() {

        @Override

        public Predicate toPredicate(Root<Report> root, CriteriaQuery<?> query, CriteriaBuilder cb) {

            List<Predicate> predicateList = new ArrayList<Predicate>();

            // ID

            if (reportVo.getReportId()!=null && !"".equals(reportVo.getReportId())) {

                predicateList.add(cb.like(root.get("reportId").as(String.class), "%"+(String)reportVo.getReportId()+"%"));

            }

            // 报表名称

            if (reportVo.getReportName()!=null && !"".equals(reportVo.getReportName())) {

                predicateList.add(cb.like(root.get("reportName").as(String.class), "%"+(String)reportVo.getReportName()+"%"));

            }

            // 菜单id

            if (reportVo.getMenuId()!=null && !"".equals(reportVo.getMenuId())) {

                predicateList.add(cb.like(root.get("menuId").as(String.class), "%"+(String)reportVo.getMenuId()+"%"));

            }

            // 状态

            if (reportVo.getStatus()!=null && !"".equals(reportVo.getStatus())) {

                predicateList.add(cb.like(root.get("status").as(String.class), "%"+reportVo.getStatus()+"%"));

            }

            //Join代表链接查询,通过root对象获取。创建的过程中,第一个参数为关联对象的属性名称,第二个参数为连接查询的方式(left,inner,right)

            //JoinType.LEFT:左外连接;JoinType.INNER:内连接;JoinType.RIGHT:右外连接

            Join<Report, Menu> join = root.join("menu",JoinType.INNER);

            if (reportVo.getMenuName()!=null && !"".equals(reportVo.getMenuName())) {

                predicateList.add(cb.like(join.get("menuName").as(String.class), "%"+reportVo.getMenuName()+"%"));

            }

            return cb.and( predicateList.toArray(new Predicate[predicateList.size()]));

        }

    };

}

3、测试:

     

package com.tc.report.service;

import java.util.List;

import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;

import com.tc.report.TcReportApplicationTests;
import com.tc.report.VO.PageResult;
import com.tc.report.VO.ReportVo;
import com.tc.report.dataobject.Report;

public class ReportServiceTest extends TcReportApplicationTests{
	
	@Autowired
	private ReportService reportService;
	
	@Test
	public void testLoadAllReports(){
		ReportVo reportVo = new ReportVo();
		reportVo.setMenuName("销售");
		PageResult result = reportService.loadAllReports(reportVo);
		List<Report> reports = (List<Report>) result.getData();
		for (Report report: reports){
			System.out.println(report);
		}
	}

}

以上,个人整理。如有错漏之处,欢迎大家指正。谢谢!

spring-data-jpa原sql语句多表关联查询+分页+自定义数据返回封装请参考我的另一篇文章:

https://blog.csdn.net/yandype/article/details/95318828

 

 

 

  • 0
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
您好!关于Spring Data JPA分页查询,您可以按照以下步骤进行操作: 1. 首先,确保您的项目中已经引入了Spring Data JPA依赖,以及相关的数据库驱动依赖。 2. 创建一个继承自JpaRepository的接口,用于定义您的数据访问操作。例如: ```java import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; @Repository public interface UserRepository extends JpaRepository<User, Long> { // 在这里可以定义各种自定义的查询方法 } ``` 3. 在您的Service层或者Controller层注入该Repository,并使用其提供的分页方法进行查询。例如: ```java import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; import org.springframework.stereotype.Service; @Service public class UserService { @Autowired private UserRepository userRepository; public Page<User> getUsersByPage(int pageNum, int pageSize) { PageRequest pageRequest = PageRequest.of(pageNum, pageSize); return userRepository.findAll(pageRequest); } } ``` 在上述示例中,我们通过调用`userRepository.findAll(pageRequest)`方法实现了分页查询,并传入`PageRequest`对象来指定页码和每页大小。 4. 最后,在您的Controller层中使用该Service方法来处理分页查询请求,并将结果返回给前端。例如: ```java import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Page; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; @RestController public class UserController { @Autowired private UserService userService; @GetMapping("/users") public Page<User> getUsersByPage(@RequestParam int pageNum, @RequestParam int pageSize) { return userService.getUsersByPage(pageNum, pageSize); } } ``` 在上述示例中,我们通过`@RequestParam`注解来接收前端传递的pageNum和pageSize参数,并调用UserService中的方法进行查询。 这样,您就可以使用Spring Data JPA进行分页查询了。希望能对您有所帮助!如果您还有其他问题,请随时提问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值