Spring Data Jpa多表查询返回自定义实体方式

目录
  • SpringDataJpa多表查询返回自定义实体
    • Repository
    • 好下面到单元测试
    • 自定义实体
  • SpringDataJpa多表查询返回自定义VO的问题
    • 下面是我的代码
    • 下面是我的dao层,重点

SpringDataJpa多表查询返回自定义实体

比如来看一下这样的一条SQL语句,这是一个三张表的多表查询,显然在JPA中用一个实体类是接受不了这些参数的

select 
t1.id as chapterId ,
t1.name as chapterName ,
t2.id as unitId,
t2.name as unitName ,
t3.id as lessonId,
t3.name as lessonName
from  t_chapter t1
LEFT JOIN  t_unit t2 on t1.id =t2.chapter_id
LEFT JOIN t_lession t3 on t3.unit_id =t2.id 
where t1.id= '4028b4816305ea91016305eec24f0000' 
and t2.id='4028b4816305f1a6016305f423180000'
and t3.id= '4028b4816306007b016306020bb80000';

Repository

/**
 * Created by ZhuPengWei on 2018/5/11.
 */
public interface TestRepository extends JpaRepository<ProductInfo, String > {
    @Query(
            value = "select \n" +
                    "t1.id as chapterId ,t1.name as chapterName ,t2.id as unitId,t2.name as unitName ,t3.id as lessonId,t3.name as lessonName\n" +
                    "from  t_chapter t1\n" +
                    "LEFT JOIN  t_unit t2 on t1.id =t2.chapter_id\n" +
                    "LEFT JOIN t_lession t3 on t3.unit_id =t2.id \n" +
                    "where t1.id= :chapterId \n" +
                    "and t2.id=:unitId \n" +
                    "and t3.id= :lessonId",
            nativeQuery = true
    )
    List<Object[]> select(@Param("chapterId") String chapterId, @Param("unitId") String unitId, @Param("lessonId") String lessonId);
}

好下面到单元测试

/**
 * Created by ZhuPengWei on 2018/5/11.
 */
@RunWith(SpringRunner.class)
@SpringBootTest
public class TestRepositoryTest {
    @Autowired
    private TestRepository testRepository;
    @Test
    public void select() throws Exception {
        List<Object[]> select = testRepository.select("4028b4816305ea91016305eec24f0000", "4028b4816305f1a6016305f423180000", "4028b4816306007b016306020bb80000");
        List<TestView> testViews = castEntity(select, TestView.class);
        Assert.assertTrue(testViews.size() > 0);
    }
    //转换实体类
   public static <T> List<T> castEntity(List<Object[]> list, Class<T> clazz) throws Exception {
        List<T> returnList = new ArrayList<T>();
        if(CollectionUtils.isEmpty(list)){
            return returnList;
        }
        Object[] co = list.get(0);
        Class[] c2 = new Class[co.length];
        //确定构造方法
        for (int i = 0; i < co.length; i++) {
            if(co[i]!=null){
                c2[i] = co[i].getClass();
            }else {
                c2[i]=String.class;
            }
        }
        for (Object[] o : list) {
            Constructor<T> constructor = clazz.getConstructor(c2);
            returnList.add(constructor.newInstance(o));
        }
        return returnList;
    }

自定义实体

/**
 * Created by ZhuPengWei on 2018/5/11.
 */
@Data
public class TestView {
    private String chapterId;
    private String chapterName;
    private String unitId;
    private String unitName;
    private String lessonId;
    private String lessonName;
    public TestView() {
    }
    public TestView(String chapterId, String chapterName, String unitId, String unitName, String lessonId, String lessonName) {
        this.chapterId = chapterId;
        this.chapterName = chapterName;
        this.unitId = unitId;
        this.unitName = unitName;
        this.lessonId = lessonId;
        this.lessonName = lessonName;
    }
}

需要注意的是 SQL语句的字段顺序一定要与实体类字段的顺序保持一致,否则会出现参数封装错误的情况

Spring Data Jpa多表查询返回自定义VO的问题

这两天开了一个新项目,使用SpringBoot+SpringData,  刚做了一个小功能,都是一张表的操作没什么问题,今天设计到了两张表联查,两张表各取了几个字段,组合成了一个vo, 当我用原生sql查询时报出 “找不到转换器”,当我用JPQL查询时,报出 xxx is not mapped.。 着实浪费了些时间。

其实最大的根本原因在于, 当使用JPQL 查询时,我们 FROM 的表名就不能是实体上@Table 注解中的表名,而是对应的实体的类名,记住是类名,并且查询的字段要是 实体类的属性,而不是数据库字段。切记。

下面是我的代码

package com.wisdombud.dama.quality.datasource.pojo;
import java.io.Serializable;
import java.util.Date;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
import javax.validation.constraints.NotBlank;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.ToString;
@Entity
@Table(name = "DATA_SOURCE")
@SequenceGenerator(name = "ID_SEQ", sequenceName = "SEQ_DATA_SOURCE", allocationSize = 1)
@ToString
public class DataSourcePojo implements Serializable{
    private static final long serialVersionUID = 4658654420795590006L;
    private Long id;
    @NotBlank(message = "数据源名称不能为空!")
    private String name;

    @NotBlank(message = "ip地址不能为空!")
    private String ip;

    @NotBlank(message = "端口号不能为空!")
    private String port;

    @NotBlank(message = "服务名不能为空!")
    private String serviceName;

    @NotBlank(message = "用户名不能为空!")
    private String userName;

    @NotBlank(message = "密码不能为空!")
    private String password;
    private String managerBranch;
    private String leadingCadre;
    private String phone;
    private Long sortIndex;
    private String remark;
    private Long createUserId;
    private String createUserName;

    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
    private Date createTime;
    private Date lastUpdateTime;
    private String re1;
    private String re2;
    private String re3;
    private String re4;

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "ID_SEQ")
    @Column(name = "ID", unique = true, nullable = false, precision = 18, scale = 0)
    public Long getId() {
        return id;
    }
    public void setId(Long id) {
        this.id = id;
    }

    @Column(name = "NAME")
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }

    @Column(name = "IP")
    public String getIp() {
        return ip;
    }
    public void setIp(String ip) {
        this.ip = ip;
    }

    @Column(name = "PORT")
    public String getPort() {
        return port;
    }
    public void setPort(String port) {
        this.port = port;
    }

    @Column(name = "SERVICE_NAME")
    public String getServiceName() {
        return serviceName;
    }
    public void setServiceName(String serviceName) {
        this.serviceName = serviceName;
    }

    @Column(name = "USER_NAME")
    public String getUserName() {
        return userName;
    }
    public void setUserName(String userName) {
        this.userName = userName;
    }

    @Column(name = "PASSWORD")
    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }

    @Column(name = "MANAGER_BRANCH")
    public String getManagerBranch() {
        return managerBranch;
    }
    public void setManagerBranch(String managerBranch) {
        this.managerBranch = managerBranch;
    }

    @Column(name = "LEADING_CADRE")
    public String getLeadingCadre() {
        return leadingCadre;
    }
    public void setLeadingCadre(String leadingCadre) {
        this.leadingCadre = leadingCadre;
    }

    @Column(name = "PHONE")
    public String getPhone() {
        return phone;
    }
    public void setPhone(String phone) {
        this.phone = phone;
    }

    @Column(name = "SORT_INDEX")
    public Long getSortIndex() {
        return sortIndex;
    }
    public void setSortIndex(Long sortIndex) {
        this.sortIndex = sortIndex;
    }

    @Column(name = "REMARK")
    public String getRemark() {
        return remark;
    }
    public void setRemark(String remark) {
        this.remark = remark;
    }

    @Column(name = "CREATE_USER_ID")
    public Long getCreateUserId() {
        return createUserId;
    }
    public void setCreateUserId(Long createUserId) {
        this.createUserId = createUserId;
    }

    @Column(name = "CREATE_USER_NAME")
    public String getCreateUserName() {
        return createUserName;
    }
    public void setCreateUserName(String createUserName) {
        this.createUserName = createUserName;
    }

    @Column(name = "CREATE_TIME")
    public Date getCreateTime() {
        return createTime;
    }
    public void setCreateTime(Date createTime) {
        this.createTime = createTime;
    }

    @Column(name = "LAST_UPDATE_TIME")
    public Date getLastUpdateTime() {
        return lastUpdateTime;
    }
    public void setLastUpdateTime(Date lastUpdateTime) {
        this.lastUpdateTime = lastUpdateTime;
    }

    @Column(name = "RE1")
    public String getRe1() {
        return re1;
    }
    public void setRe1(String re1) {
        this.re1 = re1;
    }

    @Column(name = "RE2")
    public String getRe2() {
        return re2;
    }
    public void setRe2(String re2) {
        this.re2 = re2;
    }

    @Column(name = "RE3")
    public String getRe3() {
        return re3;
    }
    public void setRe3(String re3) {
        this.re3 = re3;
    }

    @Column(name = "RE4")
    public String getRe4() {
        return re4;
    }
    public void setRe4(String re4) {
        this.re4 = re4;
    }
}
package com.wisdombud.dama.quality.datasource.tablerelation.pojo;
import java.io.Serializable;
import java.util.Date;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
import lombok.ToString;
/**
 * 表关系实体
 * @author qiaoyutao
 * @Date: 2019年7月4日 上午11:40:10
 */
@Entity
@Table(name = "TABLE_RELATION")
@SequenceGenerator(name = "ID_SEQ", sequenceName = "SEQ_TABLE_RELATION", allocationSize = 1)
@ToString
public class TableRelationPojo implements Serializable{
    private static final long serialVersionUID = -9058973373224769393L;
    private Long id;
    private Long dataSourceId;
    private String tableName;
    private String columnName;
    private String relationTableName;
    private String relationColumnName;
    private String remark;
    private Long createUserId;
    private String createUserName;
    private Date createTime;
    private Date lastUpdateTime;
    private String re1;
    private String re2;
    private String re3;
    private String re4;

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "ID_SEQ")
    @Column(name = "ID", unique = true, nullable = false, precision = 18, scale = 0)
    public Long getId() {
        return id;
    }
    public void setId(Long id) {
        this.id = id;
    }

    @Column(name = "DATA_SOURCE_ID")
    public Long getDataSourceId() {
        return dataSourceId;
    }
    public void setDataSourceId(Long dataSourceId) {
        this.dataSourceId = dataSourceId;
    }

    @Column(name = "TABLE_NAME")
    public String getTableName() {
        return tableName;
    }
    public void setTableName(String tableName) {
        this.tableName = tableName;
    }

    @Column(name = "COLUMN_NAME")
    public String getColumnName() {
        return columnName;
    }
    public void setColumnName(String columnName) {
        this.columnName = columnName;
    }

    @Column(name = "RELATION_TABLE_NAME")
    public String getRelationTableName() {
        return relationTableName;
    }
    public void setRelationTableName(String relationTableName) {
        this.relationTableName = relationTableName;
    }

    @Column(name = "RELATION_COLUMN_NAME")
    public String getRelationColumnName() {
        return relationColumnName;
    }
    public void setRelationColumnName(String relationColumnName) {
        this.relationColumnName = relationColumnName;
    }

    @Column(name = "REMARK")
    public String getRemark() {
        return remark;
    }
    public void setRemark(String remark) {
        this.remark = remark;
    }

    @Column(name = "CREATE_USER_ID")
    public Long getCreateUserId() {
        return createUserId;
    }
    public void setCreateUserId(Long createUserId) {
        this.createUserId = createUserId;
    }

    @Column(name = "CREATE_USER_NAME")
    public String getCreateUserName() {
        return createUserName;
    }
    public void setCreateUserName(String createUserName) {
        this.createUserName = createUserName;
    }

    @Column(name = "CREATE_TIME")
    public Date getCreateTime() {
        return createTime;
    }
    public void setCreateTime(Date createTime) {
        this.createTime = createTime;
    }

    @Column(name = "LAST_UPDATE_TIME")
    public Date getLastUpdateTime() {
        return lastUpdateTime;
    }
    public void setLastUpdateTime(Date lastUpdateTime) {
        this.lastUpdateTime = lastUpdateTime;
    }

    @Column(name = "RE1")
    public String getRe1() {
        return re1;
    }
    public void setRe1(String re1) {
        this.re1 = re1;
    }

    @Column(name = "RE2")
    public String getRe2() {
        return re2;
    }
    public void setRe2(String re2) {
        this.re2 = re2;
    }

    @Column(name = "RE3")
    public String getRe3() {
        return re3;
    }
    public void setRe3(String re3) {
        this.re3 = re3;
    }

    @Column(name = "RE4")
    public String getRe4() {
        return re4;
    }
    public void setRe4(String re4) {
        this.re4 = re4;
    }
}

下面是我的dao层,重点

package com.wisdombud.dama.quality.datasource.tablerelation.dao;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.jpa.repository.Query;
import com.wisdombud.dama.quality.datasource.tablerelation.pojo.TableRelationPojo;
import com.wisdombud.dama.quality.datasource.tablerelation.vo.TableRelationGridVo;
public interface TableRelationDao extends JpaRepository<TableRelationPojo, Long>, JpaSpecificationExecutor<TableRelationPojo>{

    // 这里使用JPQL来写的, 区别就是 new 一个vo名,最好带上全路径,并且vo中要有有参构造器,构造器签名要与查询的字段一致, 查询的属性都是实体类中的属性名,不是数据库的字段名,这点切记。
    @Query(value = "SELECT new com.wisdombud.dama.quality.datasource.tablerelation.vo.TableRelationGridVo(re.id, "
            + "ds.name, re.tableName, re.columnName, "
            + "re.relationTableName, re.relationColumnName, "
            + "re.createTime) "
            + "FROM TableRelationPojo re left join DataSourcePojo ds on re.dataSourceId = ds.id")
    public Page<TableRelationGridVo> page(Pageable pageable);
}

以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • SpringBoot+JPA 分页查询指定列并返回指定实体方式

    目录 SpringBoot+JPA分页查询指定列并返回指定实体 SpringBoot JPA实现自定义语句分页查询 SpringBoot+JPA分页查询指定列并返回指定实体 用习惯Mybatis,没用过jpa 真是各种踩坑了 脑壳疼,一个分页弄老半天,原来就一句话的事情,唉 先来说说正常的JPA如何操作 实体类对应表来创建,举个例子 @Entity @Table(name = "td_user") public class TdUser extends BaseModel { priv

  • spring data jpa 查询自定义字段,转换为自定义实体方式

    目标:查询数据库中的字段,然后转换成 JSON 格式的数据,返回前台. 环境:idea 2016.3.4, jdk 1.8, mysql 5.6, spring-boot 1.5.2 背景:首先建立 entity 映射数据库(非专业 java 不知道这怎么说) @Entity @Table(name = "user") public class User { @Id @GeneratedValue(strategy = GenerationType.AUTO) private Long

  • Spring Data JPA映射自定义实体类操作

    目录 Spring Data JPA映射自定义实体类 JPA 配置类实体映射示例 Spring Data JPA映射自定义实体类 这个问题困扰了我2天=-=,好像也能使用 jpql解决 先说下自己的功能:查询oracle最近sql执行记录 sql很简单:[如果需要分页,需要自己手动分页,因为你使用分页工具他第一页查询不会查询rownum,第二页查询就会查询rownum,然而这个返回的List<Object[]>中的参数必须要和实体类中一一对应,所以这就有一个不可控制的属性rownum,所以我们

  • Spring Data JPA实现查询结果返回map或自定义的实体类

    目录 Spring Data JPA查询结果返回map或自定义的实体类 1.工具类 2.具体应用 spingboot:jpa:Spring data jpa 返回map 结果集 Spring Data JPA查询结果返回map或自定义的实体类 在JPA中我们可以使用entityManager.createNativeQuery()来执行原生的SQL语句,并且JPA的底层实现都是支持返回Map对象的. 例如: EclipseLink 的 query.setHint(QueryHints.RESUL

  • Spring Data Jpa多表查询返回自定义实体方式

    目录 SpringDataJpa多表查询返回自定义实体 Repository 好下面到单元测试 自定义实体 SpringDataJpa多表查询返回自定义VO的问题 下面是我的代码 下面是我的dao层,重点 SpringDataJpa多表查询返回自定义实体 比如来看一下这样的一条SQL语句,这是一个三张表的多表查询,显然在JPA中用一个实体类是接受不了这些参数的 select  t1.id as chapterId , t1.name as chapterName , t2.id as unitI

  • JPA如何使用nativequery多表关联查询返回自定义实体类

    目录 JPA nativequery多表关联查询返回自定义实体类 JPA多表关联的实现方式 优缺点对比 使用sql并返回自定义实体类 JPA多表关联动态查询(自定义sql语句) 实体类 注解解释 测试类 打印结果 TestVo实体接收类 JPA nativequery多表关联查询返回自定义实体类 JPA官方推荐的多表关联查询使用不便,接触的有些项目可能会使用JPA 做简单查询,Mybaits做复杂查询.所以想要寻找一种好用的解决方案. JPA多表关联的实现方式 1.使用Specification

  • Spring Data JPA框架快速入门之自定义Repository接口

    目录 自定义Repository接口 repository接口定义 使用Repository接口 自定义Repository接口 要定义一个repository接口,你首先需要自定义一个实体类专用的Repository接口.该接口必须扩展 Repository,并将其类型指定为实体类和实体类的 ID 类型. 如果你想为该实体类资源类型开放CRUD方法,请直接继承CrudRepository而不是Repository. repository接口定义 通常,你的repository接口会扩展Repo

  • Spring Data JPA 建立表的联合主键

    最近遇到了一个小的问题,就是怎么使用 Spring Data JPA 建立表的联合主键?然后探索出了下面的两种方式. 第一种方式: 第一种方式是直接在类属性上面的两个字段都加上 @Id 注解,就像下面这样,给 stuNo 和 stuName 这两个字段加上联合主键: @Entity @Table(name = "student") public class Student { @Id @Column(name = "stu_no", nullable = false

  • Spring Data JPA实现动态查询的两种方法

    前言 一般在写业务接口的过程中,很有可能需要实现可以动态组合各种查询条件的接口.如果我们根据一种查询条件组合一个方法的做法来写,那么将会有大量方法存在,繁琐,维护起来相当困难.想要实现动态查询,其实就是要实现拼接SQL语句.无论实现如何复杂,基本都是包括select的字段,from或者join的表,where或者having的条件.在Spring Data JPA有两种方法可以实现查询条件的动态查询,两种方法都用到了Criteria API. Criteria API 这套API可用于构建对数据

  • Spring Data JPA分页复合查询原理解析

    Spring Data JPA是Spring Data家族的一部分,可以轻松实现基于JPA的存储库. 此模块处理对基于JPA的数据访问层的增强支持. 它使构建使用数据访问技术的Spring驱动应用程序变得更加容易. 在相当长的一段时间内,实现应用程序的数据访问层一直很麻烦. 必须编写太多样板代码来执行简单查询以及执行分页和审计. Spring Data JPA旨在通过减少实际需要的工作量来显著改善数据访问层的实现. 作为开发人员,您编写repository接口,包括自定义查找器方法,Spring

  • Spring Data Jpa 中原生查询 REGEXP 的使用详解

    目录 Spring Data Jpa原生查询 REGEXP 的使用 spring data jpa 原生查询(查一个json中的某一字段) Spring Data Jpa原生查询 REGEXP 的使用 REGEXP 与like 有通用之处, 单 regexp 有更好的精确度,更加自由灵活 在jpa 中使用时 :其中 定位符 ^ 在jpa @query 注解中使用时需要加上引用号 e.g @Query(value = "select p.id as id from zt_products AS p

  • SpringBoot Data JPA 关联表查询的方法

    SpringBoot Data JPA实现 一对多.多对一关联表查询 开发环境 IDEA 2017.1 Java1.8 SpringBoot 2.0 MySQL 5.X 功能需求 通过关联关系查询商店Store中所有的商品Shop,商店对商品一对多,商品对商店多对一,外键 store_id存在于多的一方.使用数据库的内连接语句. 表结构 tb_shop tb_store 实体类,通过注解实现 1.商店类Store.java package com.gaolei.Entity; import ja

  • spring data jpa如何只查询实体部分字段

    需求 现在有一张article表,用来储存文章,对应的实体类如下: package com.qianyucc.blog.model; import lombok.*; import javax.persistence.*; /** * @author lijing * @date 2019-08-05 14:28 * @description 文章 */ @Data @Entity @Table(name = "article") public class Article { @Id

  • 详解Spring Data JPA动态条件查询的写法

    我们在使用SpringData JPA框架时,进行条件查询,如果是固定条件的查询,我们可以使用符合框架规则的自定义方法以及@Query注解实现. 如果是查询条件是动态的,框架也提供了查询接口. JpaSpecificationExecutor 和其他接口使用方式一样,只需要在你的Dao接口继承即可(官网代码). public interface CustomerRepository extends CrudRepository<Customer, Long>, JpaSpecification

随机推荐