Spring Data JPA 动态多表关联查询

一、引言

在JPA中,为了实现某些复杂的sql语句查询可以借助JPA EntityManager来实现该功能,EntityManager是JPA中用于增删改查的接口,它的作用相当于一座桥梁,连接内存中的java对象和数据库的数据存储。

二、实现

  1. 下面是简单的Dao层实现
import org.springframework.stereotype.Repository;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import javax.persistence.EntityManager;
import javax.persistence.Query;
import java.math.BigInteger;
import java.util.HashMap;
import java.util.Map;


@Repository
public class tDaoImpl {

    @Autowired
    private EntityManager entityManager;

    @Override
    public Page<Output> queryMBomDetailsByIdAndStatus(Input input) {

        /**查询列表详细内容**/
        StringBuffer sql = new StringBuffer("SELECT m.a,m.b,m.c,m.d,m.e,m.f,u.g,u.h" +
                " FROM table1 m " +
                "LEFT JOIN table2 u ON m.x = u.x WHERE 1=1 ");

        Map<String, Object> map = new HashMap<>();
        if (!StringUtils.isEmpty(input.getBomMid())) {
            sql.append(" and m.id = :id ");
            map.put("id", input.getBomMid());
        }
        if (null != input.getStatus()) {
            sql.append(" and m.name = :name ");
            map.put("name", input.getStatus());
        }
        if (!StringUtils.isEmpty(input.getAccountMid())) {
            sql.append(" and u.sn = :sn ");
            map.put("accountMid", input.getAccountMid());
        }
        sql.append(" ORDER BY m.create_At DESC");

        //第二个参数是输出的实体类
        Query query = entityManager.createNativeQuery(sql.toString(),Output.class);
        query.setFirstResult((input.getPageIndex() - 1) * input.getPageSize());//第一条位置
        query.setMaxResults(input.getPageSize());//查询结果最大容量

        /**查询数据总条数**/
        String sqlStr = sql.toString();
        String count = "SELECT count(1) ";
        String substring = sqlStr.substring(0, sql.indexOf("FROM"));
        String countSql = sqlStr.replace(substring, count);
        Query countQuery = entityManager.createNativeQuery(countSql);

        //拼接查询条件
        for (String key : map.keySet()) {
            query.setParameter(key, map.get(key));
            countQuery.setParameter(key, map.get(key));
        }

        List<Output> list = query.getResultList();//详细集合
        long total = ((BigInteger) countQuery.getSingleResult()).longValue();//总数量
        
        //分页信息
        PageRequest pageable = PageRequest.of(input.getPageIndex() - 1, input.getPageSize());
        //为了方便分页查询,可将结果分装到org.springframework.data.domain.Page;类中
        Page<Output> resultPage = new PageImpl<>(list, pageable, total);

        return resultPage;

    }
}

2.注意事项

在Query query = entityManager.createNativeQuery(sql.toString(),Output.class);中输出的实体包含Date等特殊类型的数据时会报org.springframework.orm.jpa.JpaSystemException: Unknown entity的错误,此时建议最好映射的是String类型的内容,同时输出的Entity同普通JPA一样,要实现下面的注解

3.其他

在Dao层中查询的结果也可以通过下面的方法将结果放到List集合中

//重要:可将查询结果以map返回,key为查询的sql字段名
       query.unwrap(NativeQueryImpl.class).setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
       List<Output> resultList = new ArrayList<>();//结果数据
       for (Object o : list) {
           Output Output = new Output();
           Map mapResult = (HashMap) o;

           Output.setA(String.valueOf(mapResult.get("a")));
           Output.setB(String.valueOf(mapResult.get("b")));
           Output.setC(String.valueOf(mapResult.get("c")));
           Output.setD(String.valueOf(mapResult.get("d")));//
           resultList.add(Output);
       }

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Spring Data JPA可以通过使用@Query注解和JPQL语句来实现多表联合查询。在JPQL语句中,可以使用JOIN关键字来连接多个表,并使用ON子句来指定连接条件。例如: @Query("SELECT u.username, p.title FROM User u JOIN u.posts p ON u.id = p.userId") List<Object[]> findUserAndPost(); 这个例子中,User和Post是两个实体类,它们之间通过userId属性建立了关联关系。通过JOIN关键字和ON子句,我们可以将两个表连接起来,并查询出用户名和文章标题。最终返回的是一个Object数组,包含了查询结果中的两个字段。 除了使用@Query注解,Spring Data JPA还提供了一些方法命名规则,可以自动生成查询语句。例如,如果我们在UserRepository中定义一个方法: List<User> findByPostsTitle(String title); Spring Data JPA会自动根据方法名生成查询语句,查询所有标题为指定值的文章所属的用户。这个方法名中的“Posts”是User实体类中的一个属性,它表示用户发表的所有文章。通过这种方式,我们可以方便地进行多表联合查询,而不需要手动编写复杂的SQL语句。 ### 回答2: Spring Data JPASpring Framework的一个模块,它提供了SpringJPA之间的集成,并支持快速开发具有CRUD功能的应用程序。在多表联合查询中,Spring Data JPA可以使用JPQL或原生SQL语句来查询多个表,并通过实体类的关系来建立表之间的关联。下面将具体介绍如何使用Spring Data JPA进行多表联合查询。 1. 使用JPQL进行多表联合查询 使用JPQL进行多表联合查询比使用原生SQL语句更方便,因为可以直接使用实体类和属性名来代替表名和列名。 例如,我们有两个实体类:Customer和Order,它们之间是多对一的关系,即一个客户可以下多个订单。我们可以使用以下JPQL查询语句来查询所有客户及其对应的订单: ``` @Query("SELECT c, o FROM Customer c LEFT JOIN c.orders o") List<Object[]> findCustomerWithOrder(); ``` 这里使用了LEFT JOIN关键字来连接两个表,LEFT JOIN表示左连接,即返回左表(这里是Customer表)中所有数据和右表(这里是Order表)中匹配的数据。在SELECT语句中,我们选择了两个实体类,分别用c和o来代表它们,并将它们放在一个数组中返回。这样就可以查询到所有客户及其对应的订单。 2. 使用原生SQL语句进行多表联合查询 如果使用JPQL不能满足需求,也可以使用原生SQL语句来进行多表联合查询。这时需要使用EntityManager来执行SQL语句。 例如,我们有两个表:Customer和Order,它们之间的关系同上。我们可以使用以下SQL语句来查询所有客户及其对应的订单: ``` SELECT c.*, o.* FROM customer c LEFT JOIN orders o ON c.id = o.customer_id ``` 在EntityManager中,可以使用createNativeQuery方法来创建原生SQL语句的查询对象,以及setParameter方法来设置查询参数(如果有的话)。例如: ``` String sql = "SELECT c.*, o.* FROM customer c LEFT JOIN orders o ON c.id = o.customer_id"; Query query = entityManager.createNativeQuery(sql); List<Object[]> resultList = query.getResultList(); ``` 这里使用了Query.getResultList方法来返回结果集,它返回的是一个包含多个数组的列表,每个数组对应一行查询结果。数组中的元素按照SELECT语句的顺序排列。 总结 Spring Data JPA提供了方便的方法来进行多表联合查询,可以使用JPQL或原生SQL语句来查询多个表,并通过实体类之间的关系建立表之间的关联。使用JPQL可以更方便地查询,而使用原生SQL语句可以更灵活地满足各种查询需求。 ### 回答3: Spring Data JPASpring Data项目的一部分,它通过JPA规范提供了ORM解决方案。在关系型数据库中,一个数据库通常由多张表组成,而在开发过程中,我们经常需要对这些表进行查询、修改、删除等操作,如果我们需要进行多表查询,该如何实现呢? Spring Data JPA 提供了多种方式实现多表联合查询,下面我们对这些方式进行一一介绍。 1.通过JPA关联查询实现多表联合 JPA提供了两种形式的关联查询:内部关联查询和左外关联查询,这两种关联查询可以满足大部分复杂查询的需求。 内部关联查询:通过@Table注解中@TableJoinColumn属性或@JoinColumn注解,将两个实体类之间的关联关系定义在Java类中。定义完关联关系后,可以通过JPQL或Spring Data JPA提供的函数查询方法实现联合查询。 左外关联查询Spring Data JPA还提供了@Query注解的方式,开发者可以自行编写JPQL或SQL语句实现多表联合查询,并通过@Query注解进行绑定。 2.通过Criteria API实现多表联合 Criteria API是JPA提供的查询语言的一种形式,它允许开发人员通过程序生成查询语句,而不必编写具体的SQL或JPQL语句。使用Criteria API时,只需要将实体类的基本属性与关联属性设定好之后,生成一个CriteriaBuilder对象,就可以构建复杂的查询语句。 3.通过Spring Data JPA提供的命名查询实现多表联合 Spring Data JPA提供了命名查询的方式,命名查询是通过在Repository中定义方法的名称和方法的输入参数来实现的。命名查询是一个声明式的查询,开发者可以指定所需的查询字符串和返回值。 总而言之,Spring Data JPA提供了多种方式实现多表联合查询,并且具有简洁、高效、易维护等特点,开发者可以根据需求选择最合适的方式来实现多表联合查询。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值