【问题标题】:Why spring boot jpa hibernate projection throws exception?为什么spring boot jpa hibernate投影会抛出异常?
【发布时间】:2020-12-27 09:40:03
【问题描述】:

我正在使用 Spring Boot,并尝试使用投影,因为我的课程非常大,而且我一次需要所有数据的时候并不多。于是我上网找到了 Spring Boot 的网站,它提供了预测。应该很简单,是的,但由于某种原因它抛出了这个异常:

java.lang.IllegalArgumentException: Requested tuple value [index=0, realType=com.media.daos.ProjectDAO] cannot be assigned to requested type [java.util.Set]
    at org.hibernate.jpa.spi.TupleBuilderTransformer$HqlTupleImpl.get(TupleBuilderTransformer.java:136)
    at org.hibernate.jpa.spi.TupleBuilderTransformer$HqlTupleImpl.get(TupleBuilderTransformer.java:172)
    at org.springframework.data.jpa.repository.query.AbstractJpaQuery$TupleConverter.convert(AbstractJpaQuery.java:324)
    at org.springframework.data.repository.query.ResultProcessor$ChainingConverter.convert(ResultProcessor.java:228)
    at org.springframework.data.repository.query.ResultProcessor$ChainingConverter.lambda$and$0(ResultProcessor.java:214)
    at org.springframework.data.repository.query.ResultProcessor$ChainingConverter.convert(ResultProcessor.java:228)
    at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:195)
    at java.base/java.util.ArrayList$Itr.forEachRemaining(ArrayList.java:1033)
    at java.base/java.util.Spliterators$IteratorSpliterator.forEachRemaining(Spliterators.java:1801)
    at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:484)
    at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474)
    at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:913)
    at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
    at java.base/java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:578)
    at org.springframework.data.domain.Chunk.getConvertedContent(Chunk.java:167)
    at org.springframework.data.domain.PageImpl.map(PageImpl.java:106)
    at org.springframework.data.domain.PageImpl.map(PageImpl.java:30)
...

我真的不明白为什么,因为在这个查询中没有关于 java.util.Set 的讨论:

    @Value
    public class ProjectDetails {
        
        private String id, name, os, type;
    }

@Query(value = "select t.projects from TeamDAO t where t.name = :name", countQuery = "select count(p) from TeamDAO t inner join t.projects as p where t.name = :name")
    Page<ProjectDetails> getProjectsByName(@Param("name") String name, Pageable page);

PS:计数查询是必要的,我在另一个线程中讨论过这个问题,它是解决休眠 SQLSyntaxException 的方法。即使不应该使用它,也没有理由让它与预测混淆,所以我不知道为什么它不起作用 有什么想法吗?

编辑:根据要求:ProjectDAO 和 TeamDAO

public class ProjectDAO extends BaseEntity implements DAO {
    
    @Value
    public class ProjectDetails {
        
        private String id, name, os, type;
    }
    
    private static final long serialVersionUID = -2990447415589237412L;
    
    @Column(unique = true, updatable = false)
    private String name;
    
    @Column(length = 1024)
    private String description;
    
    private String features, os, type;
    
    @LastModifiedDate
    private long lastModified;

    @CreatedDate
    private long createdDate;
    
    @CreatedBy
    private String createdBy;
    
    @LastModifiedBy
    private String lastModifiedBy;
    
    @ToString.Exclude
    @EqualsAndHashCode.Exclude
    @ManyToMany(cascade = { CascadeType.PERSIST , CascadeType.MERGE, CascadeType.REFRESH })
    private Set<TeamDAO> teams;

    @ToString.Exclude
    @EqualsAndHashCode.Exclude
    @ManyToMany(cascade = { CascadeType.PERSIST , CascadeType.MERGE, CascadeType.REFRESH })
    private Set<ClientDAO> clients;
    
}

public class TeamDAO extends BaseEntity implements DAO {

    private static final long serialVersionUID = 8649943850027398166L;

    @Column(length = 124, unique = true)
    private String name;

    private String leader;
    
    @LastModifiedDate
    private long lastModified;

    @CreatedDate
    private long createdDate;
    
    @CreatedBy
    private String createdBy;
    
    @LastModifiedBy
    private String lastModifiedBy;

    @ToString.Exclude
    @EqualsAndHashCode.Exclude
    @OneToMany(mappedBy = "team", cascade = { CascadeType.PERSIST , CascadeType.MERGE, CascadeType.REFRESH })
    private Set<UserDAO> members;

    @ToString.Exclude
    @EqualsAndHashCode.Exclude
    @ManyToMany(mappedBy = "teams", cascade = { CascadeType.PERSIST , CascadeType.MERGE, CascadeType.REFRESH })
    private Set<ProjectDAO> projects;
}

id 属性来自 BaseEntity 类,因此不会显示在此类中。 我也认为它可能是查询,所以我没有选择 t.projects 我把select t.projects.name as name, t.projects.id as id, t.projects.os as os, t.projects.type as type 但是然后说它的an illegal attempt to dereference collection

【问题讨论】:

  • 您应该向我们展示 ProjectsDao 和 TeamDAO。可能两者之间的关系定义不正确。
  • @Deadron 我和他们一起编辑了帖子。但真的可以这样吗?我的意思是,如果我使用 ProjectDAO 而不是投影,它可以正常工作。我只是想避免从 Mysql 获取并发送我不会在这种情况下使用的其余数据

标签: java spring spring-boot hibernate


【解决方案1】:

好的,我找到了。 我只需要重新处理我的查询。这是我发布的问题。 @Query 注释必须指定我只想要这些变量。我将查询的值更改为以下内容:

@Query(value = "select new com.media.daos.ProjectDetails(p.id, p.name, p.os, p.type) from TeamDAO t inner join t.projects as p where t.name = :name", countQuery = "select count(p) from TeamDAO t inner join t.projects as p where t.name = :name")

我还发现hibernate不喜欢嵌套类,所以ProjectDetails现在是一个独立的类。在新文件中

编辑:同样从我读过的内容来看,实现映射器(不确定您需要实现/扩展哪个 spring/hibernate 类/接口)也应该可以工作,但是它映射了来自 db 的内容,因此在编辑 sql 时强制 db 发送所有内容,强制 mysql 只发送它。但不要引用我的话。如果你想这样做,请先做一些研究和事实核查

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-04-06
    • 2016-09-13
    • 2018-01-14
    • 2010-11-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多