Advertisement

spring data jpa 多表 分页 多条件 查询

阅读量:

结论如下:

用querydsl的方式。

鉴于此提供了一种方式,则建议采用该方法进行处理。对于单一实体对象而言,在单一表中可容纳多条记录的情况,则只需将动态条件直接设置为字段值即可,并无需在数据库层面进行关联关系的处理

多表的,大部分用querydsl都能实现。不能实现的,用sql实现。

在返回值方面,并无变化,在主实体类的基础上附加项被绑定到相应的属性中。要求DTO格式必须高效且规范

代码如下:

`package com.xxx.xxxxx.service.impl;

以下是基于给定规则对输入文本进行的同义改写

import javax.persistence_criteria_criterion_criteria_builder;
import javax_persistence_criteria_criterion_query;
import javax_persistence_criteria_criterion_predicate;
import javax_persistence_criteria_criterion_root;
import java.util.allocationlist;
import java.util collections list;

无法对这段代码进行有效的同义改写以降低重复率

@Autowired
private DemoStudentRepository demoStudentRepository;

@Autowired public DemoStudentServiceImpl(DemoStudentRepository demoStudentRepository) { super(demoStudentRepository); }

@Override
public int updateNameByStudentID(String name, String studentID) {
return demoStudentRepository.updateNameByStudentID(name, studentID);
}

@Override
public long countStudentsBySex(String gender) {
计算结果返回 demoStudentRepository.countBySex(gender);
}

@Override
public int deleteStudentByName(String name) {
// 调用演示学生存储库快速删除特定名称的学生
return demoStudentRepository.deleteXXXByName(name); // 删除操作支持通过名称快速执行
}

@Override
public List< DemoStudent > removeStudentByName(String name) {
returns demoStudentRepository.removeStudentByName(name);
}

/**

  • 通过查询注释与修改注释的方式更新多条记录信息

  • 输入参数:

  • @param name - 姓名

  • @param birthday - 出生日期

  • 输出结果:

  • @return - 更新后的学生成绩信息编号
    */
    public int updateNameByAge(String name, String birthday) {
    // 通过查询注释与修改注释的方式获取学生数据
    Student student = queryDemoStudentRepository();
    // 调用实现该功能的具体方法
    return student.updateNameByAge(name, birthday);
    }

  • 单个查询

  • @参数名

  • @返回值

/**

  • 查询单个(动态条件)
  • @param name
  • @param age
  • @return
    */
    @Override
    public DemoStudent findStudentPredicate(String name, String age) {
    QDemoStudent qDemoStudent=QDemoStudent.demoStudent;
    BooleanBuilder builder = new BooleanBuilder();
    if(StringUtils.isNotBlank(name)){
    builder.and(qDemoStudent.name.like("%"+name+"%"));
    }
    if(StringUtils.isNotBlank(age)){
    builder.and(qDemoStudent.age.eq(age));
    }
    //多条记录会报错
    return demoStudentRepository.findOne(builder).get();
    }

/**

  • 单一表关联 按需动态查询 谓词方式
  • @param page
  • *page: 当前分页号
  • @param rows
  • *rows: 每页行数
  • @param name
  • *name: 学生姓名
  • @param age
  • *age: 学生年龄
    */
    @SuppressWarnings("unchecked")
    public Page pageStudentListPredicate(
    Integer page,
    Integer rows,
    String name,
    String age) {
    // 根据指定分页号及行数获取对应结果集
    // 通过谓词查询获取对应的学生信息
    return demoStudentRepository.findAll(
    new PageRequest(page - 1, rows));
    }

根据分页、排序及参数查询需求,
将结果集分配给变量qDemoStudent。
初始化布尔过滤器builder。
如果字符串name不为空,则执行以下操作:
将过滤条件追加到builder中。
如果字符串age不为空,则使用OR逻辑将年龄等于age的条件追加到builder中。

该方法用于从demoStudentRepository获取所有学生数据,并通过builder构建查询条件进行筛选。
筛选条件包括指定页数前一页的数据总量、总记录数以及按年龄降序排列的结果。

/**

  • 多表集合 动态查询 predicate 方式,返回方式为主类,副类或者副类的其他字段以其他方式set进主类
  • @param page
  • @param rows
  • @param name
  • @param age
  • @return
    */
    @Override
    public Page pageStudentClassListPredicate(Integer page, Integer rows, String name, String age) {
    //分页加排序加参数查询
    QDemoStudent qDemoStudent=QDemoStudent.demoStudent;
    BooleanBuilder builder = new BooleanBuilder();
    if(StringUtils.isNotBlank(name)){
    builder.and(qDemoStudent.name.like("%"+name+"%"));
    }
    if(StringUtils.isNotBlank(age)){
    builder.or(qDemoStudent.age.eq(age));
    }
    return demoStudentRepository.pageStudentClassListPredicate(builder,PageRequest.of(page-1,rows));
    }

/**

  • 复杂关联表查询,在方法调用时会基于dsl实现生成所需的自定义对象实例
  • @return
    */
    @Override
    public List < DemoStudentVO > findStudentClassDslDTO(){
    return demoStudentRepository.findStudentClassDslDTO();
    }

/**

  • 多表查询,原始查询的方式(native sql),并且按指定的resultSetMapping返回

  • @return
    */
    @Override
    public Page pageStudentClassSqlMapResult(Integer page, Integer rows, String name, String age){
    return demoStudentRepository.pageStudentClassSqlMapResult(PageRequest.of(page-1,rows),name,age);
    }

  • 涉及多个表的集合操作,并包含多个条件,

  • 使用查询注解创建并返回DemoStudentVO对象,

  • 必须支持many-to-one关系以实现表间关联

  • @param page

  • @param rows

  • @param name

  • @param age

  • @return 学生信息列表

  • 多表集合查询需满足多条件要求,默认启用 native SQL 方式,默认返回一维数组

  • @param page

  • @param rows

  • @param name

  • @param age

  • @return 一维数组

/**

  • 使用Specification 方式分页
  • @param page
  • @param rows
  • @param name
  • @param age
  • @return
    /
    public Page < DemoStudent > pageStudentClassSpecification(Integer page, Integer rows, String name, String age) {
    //规格定义
    Specification specification = new Specification() {
    /
    *
  • 构造断言
  • @param root 实体对象引用
  • @param query 规则查询对象
  • @param cb 规则构建对象
  • @return 断言
    */
    @Override
    public Predicate toPredicate(Root root, CriteriaQuery<?> query, CriteriaBuilder cb) {
    List predicates = new ArrayList<>(); //所有的断言
    if(StringUtils.isNotBlank(name)){ //添加断言
    Predicate likeName = cb.like(root.get("name").as(String.class),name+"%");
    predicates.add(likeName);
    }
    return cb.and(predicates.toArray(new Predicate[0]));
    }
    };
    //分页信息
    Pageable pageable = PageRequest.of(page-1,rows); //页码:前端从1开始,jpa从0开始,做个转换
    //查询
    return demoStudentRepository.findAll(specification,pageable);
    }

}`

复制代码
 package com.xxxx.xxxxxx.repository.custom.impl;

    
  
    
 import com.querydsl.core.QueryResults;
    
 import com.querydsl.core.Tuple;
    
 import com.querydsl.core.types.Predicate;
    
 import com.querydsl.core.types.Projections;
    
 import com.querydsl.jpa.impl.JPAQuery;
    
 import com.querydsl.jpa.impl.JPAQueryFactory;
    
 import freemarker.template.utility.DateUtil;
    
 import org.apache.commons.lang3.StringUtils;
    
 import org.hibernate.SQLQuery;
    
 import org.hibernate.query.NativeQuery;
    
 import org.hibernate.transform.Transformers;
    
 import org.springframework.data.domain.Page;
    
 import org.springframework.data.domain.PageImpl;
    
 import org.springframework.data.domain.PageRequest;
    
 import org.springframework.data.domain.Pageable;
    
 import org.springframework.data.jpa.domain.Specification;
    
 import org.springframework.data.jpa.repository.support.Querydsl;
    
  
    
 import javax.annotation.PostConstruct;
    
 import javax.persistence.EntityManager;
    
 import javax.persistence.PersistenceContext;
    
 import javax.persistence.Query;
    
 import javax.persistence.criteria.CriteriaBuilder;
    
 import javax.persistence.criteria.CriteriaQuery;
    
 import javax.persistence.criteria.Root;
    
 import java.math.BigInteger;
    
 import java.util.ArrayList;
    
 import java.util.HashMap;
    
 import java.util.List;
    
 import java.util.Map;
    
  
    
 public class DemoStudentRepositoryImpl implements DemoStudentRepositoryCustom {
    
  
    
     @PersistenceContext
    
     private EntityManager entityManager;
    
  
    
     //查询工厂实体
    
     private JPAQueryFactory queryFactory;
    
  
    
     @PostConstruct
    
     public void init(){
    
     queryFactory = new JPAQueryFactory(entityManager);
    
     }
    
  
    
     /** * 多表查询,采用dsl的方式,返回单个实体的page列表,单实体中有其他实体
    
      * @return
    
      */
    
     @Override
    
     public Page<DemoStudent> pageStudentClassListPredicate(Predicate predicate, Pageable pageable){
    
     QDemoStudent qDemoStudent = QDemoStudent.demoStudent;
    
     QDemoClass qDemoClass = QDemoClass.demoClass;
    
     JPAQuery<Tuple> jpaQuery = queryFactory.select(qDemoStudent,qDemoClass)
    
             .from(qDemoStudent).leftJoin(qDemoClass).on(qDemoStudent.classGuid.eq(qDemoClass.classGuid))
    
             .where(predicate)
    
             .orderBy(qDemoStudent.age.desc())
    
             .offset(pageable.getOffset())
    
             .limit(pageable.getPageSize());
    
  
    
     QueryResults<Tuple> result=jpaQuery.fetchResults();
    
     List<DemoStudent> lsStudent=new ArrayList <DemoStudent>();
    
     for (Tuple row : result.getResults()) {
    
         DemoStudent student= row.get(qDemoStudent);
    
         student.setDemoClass(row.get(qDemoClass));
    
         lsStudent.add(student);
    
     }
    
     Page<DemoStudent> pageDemoStudent=new PageImpl < DemoStudent >(lsStudent,pageable,result.getTotal());
    
     return pageDemoStudent;
    
     }
    
  
    
  
    
     /** * 多表查询,采用dsl的方式,返回自定义对象
    
      * @return
    
      */
    
     @Override
    
     public List < DemoStudentVO > findStudentClassDslDTO(){
    
     QDemoStudent qDemoStudent = QDemoStudent.demoStudent;
    
     QDemoClass qDemoClass = QDemoClass.demoClass;
    
  
    
     //用下面的办法或者直接返回Tuple 对象,一个个set,例如:dto.setPrice(tuple.get(_Q_good.price));
    
     return queryFactory
    
             .select(
    
                     Projections.bean(
    
                             DemoStudentVO.class,//返回自定义实体的类型 这种方式,dto对象不要用构造函数,会报错
    
                             qDemoStudent.studentGuid,
    
                             qDemoStudent.name,
    
                             qDemoStudent.age,
    
                             qDemoStudent.birthday,
    
                             qDemoClass.className,
    
                             qDemoClass.remark.as("classRemark")//使用别名对应dto内的typeId
    
                     )
    
             )
    
             .from(qDemoStudent,qDemoClass)//构建两表笛卡尔集
    
             .where(qDemoStudent.classGuid.eq(qDemoClass.classGuid))//关联两表
    
             .orderBy(qDemoStudent.age.desc())//倒序
    
             .fetch();
    
  
    
     }
    
  
    
  
    
     /** * 多表查询,原始查询的方式(native sql),并且按以前hibernate方式返回
    
      * @return
    
      */
    
     @Override
    
     public Page<DemoStudent> pageStudentClassSqlMapResult(Pageable pageable, String name, String age) {
    
     StringBuilder countSelectSql = new StringBuilder();
    
     countSelectSql.append("select count(1)  from demo_student s "+
    
             " left join  demo_class c on s.class_guid=c.class_guid where 1=1 ");
    
  
    
     StringBuilder selectSql = new StringBuilder();
    
  
    
     selectSql.append("select {s.*},{c.*}  from demo_student s "+
    
             " left join  demo_class c on s.class_guid=c.class_guid where 1=1 ");
    
  
    
     Map<String,Object> params = new HashMap<>();
    
     StringBuilder whereSql = new StringBuilder();
    
     if(StringUtils.isNotBlank(name)){
    
         whereSql.append(" and name=:name ");
    
         params.put("name",name);
    
     }
    
     if(StringUtils.isNotBlank(age)){
    
         whereSql.append(" and age=:age ");
    
         params.put("age",age);
    
     }
    
  
    
     String countSql = new StringBuilder().append(countSelectSql).append(whereSql).toString();
    
     Query countQuery = entityManager.createNativeQuery(countSql);
    
  
    
  
    
     for(Map.Entry<String,Object> entry:params.entrySet()){
    
         countQuery.setParameter(entry.getKey(),entry.getValue());
    
     }
    
     BigInteger totalCount = (BigInteger)countQuery.getSingleResult();
    
  
    
     String querySql = new StringBuilder().append(selectSql).append(whereSql).toString();
    
  
    
     // select s.*,c.* 这种,两个表有相同字段的,因为第二个表的对应字段会用第一个表的对应字段,数据信息不对。
    
     //Query query = this.entityManager.createNativeQuery(querySql,"StudentResults");
    
     Query query = this.entityManager.createNativeQuery(querySql);
    
     for(Map.Entry<String,Object> entry:params.entrySet()){
    
         query.setParameter(entry.getKey(),entry.getValue());
    
     }
    
     query.setFirstResult((int)pageable.getOffset());
    
     query.setMaxResults(pageable.getPageSize());
    
  
    
     //query.unwrap(SQLQuery.class).addEntity("s",DemoStudent.class).addEntity("c",DemoClass.class);
    
     query.unwrap(NativeQuery.class).addEntity("s",DemoStudent.class).addEntity("c",DemoClass.class);
    
     List result =query.getResultList();//是object[]数组,第一个元素是demo_student对象,第二个元素是demo_class对象
    
     List<DemoStudent> lsStudent=new ArrayList <DemoStudent>();
    
     for (Object row : result) {
    
         DemoStudent demoStudent=(DemoStudent)((Object[])row)[0];
    
         DemoClass demoClass=(DemoClass)((Object[])row)[1];
    
         demoStudent.setDemoClass(demoClass);
    
         lsStudent.add(demoStudent);
    
     }
    
     Page<DemoStudent> pageDemoStudent=new PageImpl < DemoStudent >(lsStudent,pageable,totalCount.longValue());
    
     return pageDemoStudent;
    
     }
    
  
    
  
    
 }

参考:http://www.ityouknow.com/spring-boot.html

https://www.cnblogs.com/ityouknow/p/5891443.html

几种方式

在Hibernate配置中使用字段间采用manytoone方式进行关联的方式存在不满,在实际应用中遇到多个对象之间的关联情况时容易出现超时问题。即便采用延迟加载机制,在涉及的数据表规模较大时也难以掌控其运行效果。对于这种情况是否应该改用多表策略或直接转为sql语句处理仍存在疑问。

2.jpql方式1 通过new 对象的方式传入参数,作为返回对象,自定义对象

参考:<>

@Query(value: 从新组织架构中选择组织功能模块中的UserOutputVO对象,
包含用户姓名、邮箱,
部门名称字段并命名为departmentName,
以及参与者的数量字段并命名为roleNum
from User u )

+ "left join u.department d left join u.roles r group by u.id")

Page findUserOutputVOAllPage(Pageable pageable);

这里请注意:VO的构造方法参数必须与查询语句中的查询字段类型及数量一致。如果无法匹配则会抛出错误。

假如涉及的对象参数较多,
难道不需一一列出?
而且每个部分都有各自的特点,
这样就需要为每个情况定制不同的构造函数。
非得是都是第一层的?
或者可以直接通过传递参数的方式?
构造函数应该也可以通过传递参数的方式进行处理,
在内部进行配置设置。

不过话说回来分页的话,也不需要那么多字段

不过对应的实体类上还是需要manytoone,这种来关联表

3.jpql方式2 使用projection接口做映射与投影

public interface UserProjection {

String getName();

@value(target.email_column)//当别名与对应的getXXX方法名称不一致时,可以通过以下方式实现参数注入

String getEmail();

String getDepartmentName();

Integer getRoleNum();

}

//故意将email别名为emailColumn,以便讲解@Value的用法

@quer从User表中选择用户名、邮箱、部门名称以及角色数量。
该查询用于从用户表获取基本信息及职位分布情况。
其中包括每位用户的基本信息如用户名、邮箱地址等,
以及对应部门名称和具体参与的角色数量。
这种数据结构有助于后续分析与管理。
通过这种聚合查询,
可以高效地提取出所需的关键信息。
这种数据处理方法在实际应用中具有较高的实用价值。
通过合理设计查询语句,
可以进一步优化数据提取效率,
并支持复杂的业务逻辑实现。

+ "left join u.department d left join u.roles r group by u.id")

Page findUserProjectionAllPage(Pageable pageable)

对比之下这种方式的效果如何?它无需在代码中显式声明new变量。但必须借助返回接口的方式来处理相关信息。整体上来说总觉着有些别扭。

<>

map方式的返回:

/** * HQL基于旅店名称检索酒店及其所在城市的所有信息 * * @return */ @Query(value = "从带左连接的城市表t1和酒店表t2中提取记录" select new map(t1,t2) from TCity t1 left join THotel t2 on t1.id=t2.city where t2.name=:name) List<Map<String, Object>> findCityAndHotelByHQL(@Param("name") String name);

4.原生sql方式

//展示原生查询

@Command(value="从用户表中选择员工名称、电子邮件字段、部门名称以及角色数量统计")

部门信息左连接到u上(根据id匹配),接着角色表ur也左连接到u上(根据id匹配),然后按u的id进行分组,并限制开始索引和大小

nativeQuery = true)

List<Object[]> 用户投影的全部页面 @Param("起始编号") int 起始编号, @Param("数量限制") int 数量限制

默认返回是list<Object[]>

Pageable pageable = new PageRequest(0,5);

//如果需要的话,自行封装分页信息

Page<Object[]> page = new PageImpl<Object[]>(content, pageable, total);

当在处理数据库性能优化问题时,采用原生SQL的方式可能会更高效。然而,在大多数需求场景下使用JSON Path Query语言(JPQL)仍然较为便捷。这无疑是一种更为简便的方法。需要注意的是,在获取数据时通常都需要 pagination(分页)操作来处理大量的数据条目。当然,在某些情况下仅需获取几个字段也同样适用。

参考:<>

/** * 基于旅客姓名进行分页检索的旅馆及所在城市信息 * * @param name 旅客姓名 * @param pageable 分页参数 * @return Page<Object[]> */
@Query(
value = "SELECT CityName AS city_name, HotelName AS hotel_name",
value = value, countQuery = "SELECT COUNT(*) FROM city_info city JOIN hotel_info hotel ON hotel.city_id = city.city_id WHERE hotel.hotel_name = :name", nativeQuery = true ) public function findCityAndHotel( ?string name,
Pageable $pageable
): Page<Object[]>
{
}

5.集映射定义

map result

https://www.v2ex.com/t/333899

6.改为原生方式,直接写,entitimanager

参考:<>

@Autowired @PersistenceContext private EntityManager entityManager;
@Test public void testDynamic() throws Exception {
根据配置生成对应的CityHohel表单;
String sql = "选择新业务流程中心生成的城市表单;
从TCity表t1左连接THotel表t2,
其中t1的id字段等于t2的city字段;
并且筛选出t2.name='酒店'的数据";
根据上述SQL语句,
Query query = entityManager.createQuery(sql);
通过查询获取结果集列表;
声明并赋值resultList变量;
验证结果集非空:
resultList.size() > 0";
}

7.还有一种,自己写方法,讲方位的object对象转成对应对象

<>

将数据映射到实体对象中是一种有效的做法。然而,在实际应用中发现该方法存在一定的问题:若仅将该返回添加到实体对象上,则可能会导致数据冗余。值得注意的是,在2010年时已有研究者已经实现了类似的功能

http://www.blogjava.net/jesson2005/articles/380884.html

补充:返回的对象数组包含例如在对象数组中, object[0]表示 学生实体 ,而 object[1]则代表 班级实体 (例如以下代码段),其中在修改后的示例中 entities 数量可扩展至多个。

该文档提供了关于JavaEE持久化框架中ResultSetMapping的具体实现细节和技术规范说明,请参考完整文档获取详细信息。

参考:https://blog.jooq.org/tag/sqlresultsetmapping/

这种技术,在另一个网站上也有批评,并且从另一篇博客中了解到相关观点;同样地,在另一篇文章中提到该作者对该技术持反对态度,并认为jpa在这方面不如传统的sql方法好;值得参考的地方是https://blog.jooq.org/2013/11/13/popular-orms-dont-do-sql/

这两种都可以实现。

总结:

在SqlResultSetMapping中对应的所有字段需填写,在查询那一端也需要完整列出所有相关字段。
因为其本质是将数据库表中的字段与实体对象的属性进行一一对应。
若缺少任一端的字段对应关系,则会导致错误提示。
两端必须确保所有对应的字段都被完整列出。

如果大量使用相同的名字可能会导致修改困难。例如文中提到的那段话:如果某些关联需要使用别名,则会遇到问题。例如如果是实体加上最多一两个列,则可能需要重新命名以避免冲突;但名称最好能稍微调整以避免冲突的情况通常不成问题。

发现了差异吗?b.title字段重命名为book_title在SQL字符串中。The performance issue crashes at runtime.How can one keep in mind that they must also adapt

1 @FieldResult``(name = ``"title"``, column = ``"title"``)

… to be

1 @FieldResult``(name = ``"title"``, column = ``"book_title"``)

Conversely, how to recall that after renaming the column in your @FieldResult, you must also verify wherever this "BookAuthorMapping" is referenced, and update the column names in those queries.

除此之外还有非常庞大的数量,并且可能需要添加大量的分表来处理这些数据(例如当各个表返回的数据结构存在差异时)。尤其是当存在大量分表链接时,默认情况下系统会自动解析并获取所有相关的字段信息)。需要注意的是字段名称不需要显式声明即可默认获取数据(例如如果不做额外设置系统会自动推断并获取所有相关字段)。通常情况下也可以忽略不计这些默认获取的字段名(因为它们并不会对查询结果产生实际影响)。

代码如下:

复制代码
  
    
 @SqlResultSetMapping (
    
     name="StudentResults",
    
     entities = {
    
             @EntityResult(entityClass = DemoStudent.class,fields={
    
                     @FieldResult(name="studentGuid",column = "student_guid"),
    
                     @FieldResult(name="name",column = "name"),
    
                     @FieldResult(name="age",column = "age"),
    
               @FieldResult(name="sex",column = "sex"),
    
               @FieldResult(name="birthday",column = "birthday"),
    
               @FieldResult(name="classGuid",column = "class_guid"),
    
               @FieldResult(name="isDeleted",column = "is_deleted")
    
               /*@FieldResult(name="className",column = "class_name") 直接想写在这里,直接把班级表的名称映射到这个实体类的transient字段中,是不行的,必须是数据库的,不报错,但是也不会填充值*/
复制代码
             })

    
     },
    
     columns = {
    
             @ColumnResult(name="class_name")
    
     }
    
 )
    
 @Entity
    
 @DynamicInsert (true)
    
 @DynamicUpdate (true)
    
 @Table (name = "Demo_Student")
    
 @Where (clause="Is_Deleted=0")
    
 public class DemoStudent implements java.io.Serializable{
    
  
    
    private static final long serialVersionUID = -1L;
    
  
    
    private String studentGuid;
    
  
    
    private String name;
    
  
    
    private String age;
    
  
    
    private String sex;
    
  
    
    private Date birthday;
    
  
    
 /* private DemoClass demoClass;*/
    
  
    
  
    
    private String classGuid;
    
  
    
    private String className;
    
  
    
    private Boolean isDeleted;
    
  
    
  
    
    public DemoStudent(){
    
    }
    
  
    
    public DemoStudent(
    
       String studentGuid
    
    ){
    
       this.studentGuid = studentGuid;
    
    }
    
  
    
    @Id
    
    @GeneratedValue (generator = "pk")
    
    @GenericGenerator (name = "pk", strategy = "uuid2")
    
    @Column (name = "student_guid")
    
    public String getStudentGuid() {
    
       return this.studentGuid;
    
    }
    
    
    
    public void setStudentGuid(String value) {
    
       this.studentGuid = value;
    
    }
    
  
    
    @Column (name = "name")
    
    public String getName() {
    
       return name;
    
    }
    
  
    
    public void setName(String name) {
    
       this.name = name;
    
    }
    
  
    
    @Column (name = "age")
    
    public String getAge() {
    
       return age;
    
    }
    
  
    
    public void setAge(String age) {
    
       this.age = age;
    
    }
    
  
    
    @Column (name = "sex")
    
    public String getSex() {
    
       return sex;
    
    }
    
  
    
    public void setSex(String sex) {
    
       this.sex = sex;
    
    }
    
  
    
    @Column (name = "birthday")
    
    public Date getBirthday() {
    
       return birthday;
    
    }
    
  
    
    public void setBirthday(Date birthday) {
    
       this.birthday = birthday;
    
    }
    
  
    
 /* @ManyToOne
    
    @JoinColumn(name="class_guid",insertable = false,updatable = false)*/
    
 /* @Transient
    
    public DemoClass getDemoClass() {
    
       return demoClass;
    
    }
    
  
    
    public void setDemoClass(DemoClass demoClass) {
    
       this.demoClass = demoClass;
    
    }*/
    
  
    
    @Column (name = "class_guid")
    
    public String getClassGuid() {
    
       return classGuid;
    
    }
    
  
    
    public void setClassGuid(String classGuid) {
    
       this.classGuid = classGuid;
    
    }
    
  
    
    @Column (name = "is_deleted")
    
    public Boolean getIsDeleted() {
    
       return isDeleted;
    
    }
    
  
    
    public void setIsDeleted(Boolean isDeleted) {
    
       this.isDeleted = isDeleted;
    
    }
    
  
    
    @Transient
    
    public String getClassName() {
    
       return className;
    
    }
    
  
    
    public void setClassName(String className) {
    
       this.className = className;
    
    }
    
 }
复制代码
  
    
 @Repository
    
 public class DemoStudentDaoImpl implements DemoStudentDao{
    
     //实体管理
    
     @Autowired
    
     private EntityManager entityManager;
    
  
    
     //查询工厂
    
     private JPAQueryFactory queryFactory;
    
  
    
     public DemoStudentDaoImpl(){
    
     queryFactory=new  JPAQueryFactory(entityManager);
    
     }
    
  
    
     @Override
    
     public void pageStudentClassListDsl(PageRequest page) {
    
     Query q = entityManager.createNativeQuery(
    
             "select s.student_guid,s.name,s.age,s.birthday,s.is_deleted,s.sex,s.class_guid,c.class_name  from demo_student s " +
    
                     "left join  demo_class c on s.class_guid=c.class_guid ",
    
             "StudentResults");
    
  
    
     List resultList =q.getResultList();
    
   //这里的结果就是object数组的集合,每个object数组两个元素,第一个元素是学生实体,第二个就是classname对应的字符串
    
  
    
  
    
       return null;
    
     }
    
 }

9.ConstructorResult 方式

类似

该SQL ResultSet Mapping配置将设置为名称 'view' 以及其包含的类。该映射作用于类 TA,并包括以下字段配置:字段名为 'name' 且类型设为字符串;字段名为 'time' 且类型设为日期;字段名为 'bname' 且类型设为字符串。

这种,换要对应构造函数不方便。参考:https://www.v2ex.com/t/333899

6.弄成视图,好了,变成单表操作了

7.QueryDSL 方式,用这种把
https://www.jianshu.com/p/5c416a780b3e

  1. 遇到返回对象时难以管理, 因此我们决定替换成之前的SQL查询方式, 这样变得容易操作. 该方法能够应对各种情况, 虽然显得略显不足, 但相比起来更为简便.
复制代码
    query.unwrap(SQLQuery.class).addEntity("s",DemoStudent.class).addEntity("c",DemoClass.class);

参考:<>

全部评论 (0)

还没有任何评论哟~