spring data jpa简单crud操作以及多表关联,分页排序,复杂条件查询

分页和多表关联查询有多种方式

@Query使用

  • 单表查询所有:

public interface SubjectDao extends JpaRepository<Subject,Integer>, JpaSpecificationExecutor<User>, Serializable {
   @Query(value = "select * from subject",nativeQuery = true)
   public List<Subject> ul();
}
  • 单表分页查询
 @Test
    public void hi1(){
        Pageable page=  PageRequest.of(1,2);
        Page<Subject>kl=subjectDao.ul(page);
        System.out.println(kl.getContent().size());
        System.out.println(kl.getTotalElements());
    }
public interface SubjectDao extends JpaRepository<Subject,Integer>, JpaSpecificationExecutor<User>, Serializable {
    @Query(value = "select * from subject",nativeQuery = true)
    public Page<Subject> ul(Pageable pageable);
}
  • 多表分页查询
public interface SubjectDao extends JpaRepository<Subject,Integer>, JpaSpecificationExecutor<User>, Serializable {
    @Query(value = "select * from subject s inner join subject_auths sa on s.id=sa.subject_id",nativeQuery = true)
    Page<Subject> ul(Pageable pageable);
}

调试结果如下:
在这里插入图片描述

  • 此时只能看到subject中的信息,如果我想看到与之关连的subject_auth中的信息。可以做一对一的配置

         - subject中的配置,其中subject_id是subject_auth表中的字段,它是subject的外键
    

在这里插入图片描述
其结果如下:
在这里插入图片描述

  • 查询优化
    上述都是select *查询所有的操作。如果我只想查询部分字段。。
    注意:想当然的如果这样写
public interface SubjectDao extends JpaRepository<Subject,Integer>, JpaSpecificationExecutor<User>, Serializable {
    @Query(value = "select s.id,sa.id from subject s inner join subject_auths sa on s.id=sa.subject_id",nativeQuery = true)
    Page<Subject> ul(Pageable pageable);
}
 1. 则会报

Caused by: java.sql.SQLException: Column ‘business_scope’ not found.

spring data jpa执行完查询后,都会将结果一个一个的注入到对应的pojo的每个属性中.但由于我只查询sublect的id和subject_auth的id

select
s.id,
sa.id
from
subject s
inner join
subject_auths sa
on s.id=sa.subject_id limit ?,?

所以spring data jpa就会认为你的数据库里subject表中只有id这一个字段,subject_auth里只有id这一个字段。但你的Subject类有businessScope属性,并且做了映射@Column(name=“business_scope”),所以它从结果集中找不到这个字段名,注入到suoject对象的businessScope属性中,就抛出上述错误。

 2. 如果查出来的字段有同名的,记得取别名,否则会报错如下:

Caused by: org.hibernate.loader.custom.NonUniqueDiscoveredSqlAliasException: Encountered a duplicated sql alias [id] during auto-discovery of a native-sql query

 3. 并且还会 报==Unknown column 's' in 'field list'==

运行的sql如下(你只分页查询了部分字段,还想做统计。此时它不知道该按照那个字段做统计 )
select count(s) from subject s inner join subject_auths sa on s.id=sa.subject_id

针对以上几点问题。我做了进一步的测试

将上述语句改写成jpql语句

public interface SubjectDao extends JpaRepository<Subject,Integer>, JpaSpecificationExecutor<User>, Serializable {
    @Query(value = "From Subject s inner join SubjectAuths sa on s.id=sa.subjectId")
    Page<Object> ul(Pageable pageable);
}

在这里插入图片描述
其相应的sql:

Hibernate: 
    select
        subject0_.id as id1_13_0_,
        subjectaut1_.id as id1_14_1_,
        subject0_.business_scope as business2_13_0_,
        subject0_.enterprise_nature as enterpri3_13_0_,
        subject0_.estiblish_time as estiblis4_13_0_,
        subject0_.first_holder as first_ho5_13_0_,
        subject0_.name as name6_13_0_,
        subject0_.reg_capital as reg_capi7_13_0_,
        subject0_.reg_location as reg_loca8_13_0_,
        subject0_.tags as tags9_13_0_,
        subjectaut1_.auth_time as auth_tim2_14_1_,
        subjectaut1_.expiring_time as expiring3_14_1_,
        subjectaut1_.subject_id as subject_4_14_1_,
        subjectaut1_.user_id as user_id5_14_1_ 
    from
        subject subject0_ 
    inner join
        subject_auths subjectaut1_ 
            on (
                subject0_.id=subjectaut1_.subject_id
            ) limit ?,
        ?
Hibernate: 
    select
        count(subject0_.id) as col_0_0_ 
    from
        subject subject0_ 
    inner join
        subject_auths subjectaut1_ 
            on (
                subject0_.id=subjectaut1_.subject_id
            )

spring data jpa在使用@Query时,如果nativeQuery=true,并且只是查询部分字段,那么进行多表联查,结果集是List<Object[]>,它不能完成对结果集自动封装,只能我们自己来处理结果集。我们可以写jpql语句,再构造一个vo类型的pojo,通过select new Test(a,b,c)…让它帮我们完成封装。

spring的动态代理我觉得最明显的效果在spring data jpa中发挥的淋漓尽致。通过它完全解放了dao层的操作,可以真正让程序员有更多时间在service层操作上。-----实现了面向接口编程。实现类有spring的代理机制给你完成。

public interface SubjectDao extends JpaRepository<Subject,Integer>, JpaSpecificationExecutor<User>, Serializable {
    @Query(value = "select new org.mj.pojo.Test(s.id,sa.subjectId) from Subject s inner join SubjectAuths sa on s.id=sa.subjectId")
    Page<Test> ul(Pageable pageable);
}




@Getter
@Setter
public class Test implements Serializable {
    Integer id;
    Integer subjectId;

    public Test(Integer id,Integer subjectId){
        this.subjectId=subjectId;
        this.id=id;
    }
}

用jpql不能写 join on应该用 join where

antlr.SemanticException: Path expected for join!

测试说明:

public interface SubjectDao extends JpaRepository<Subject,Integer>, JpaSpecificationExecutor<User>, Serializable {
    @Query(value = "select s.id as sid,sa.id as said from Subject s inner join SubjectAuths sa on s.id=sa.subjectId")
    Page<Object> ul(Pageable pageable);
}

jpql语句的关联查询
https://www.cnblogs.com/acm-bingzi/p/jpqlJoin.html

Caused by: org.hibernate.hql.internal.ast.QuerySyntaxException: Unable to locate appropriate constructor on class [org.mj.pojo.Test]. Expected arguments are: long, int [select new org.mj.pojo.Test(s.id,sa.subjectId) from org.mj.pojo.Subject s inner join org.mj.pojo.SubjectAuths sa on s.id=sa.subjectId]
at org.hibernate.hql.internal.ast.QuerySyntaxException.convert(QuerySyntaxException.java:74)
at org.hibernate.hql.internal.ast.ErrorTracker.throwQueryException(ErrorTracker.java:93)
at org.hibernate.hql.internal.ast.QueryTranslatorImpl.analyze(QueryTranslatorImpl.java:277)
at org.hibernate.hql.internal.ast.QueryTranslatorImpl.doCompile(QueryTranslatorImpl.java:191)
at org.hibernate.hql.internal.ast.QueryTranslatorImpl.compile(QueryTranslatorImpl.java:143)
at org.hibernate.engine.query.spi.HQLQueryPlan.(HQLQueryPlan.java:119)
at org.hibernate.engine.query.spi.HQLQueryPlan.(HQLQueryPlan.java:80)
at org.hibernate.engine.query.spi.QueryPlanCache.getHQLQueryPlan(QueryPlanCache.java:153)
at org.hibernate.internal.AbstractSharedSessionContract.getQueryPlan(AbstractSharedSessionContract.java:611)
at org.hibernate.internal.AbstractSharedSessionContract.createQuery(AbstractSharedSessionContract.java:720)
… 132 more

  • 解决方案是:
  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值