Java 带有投影的 Spring JPA 本机查询给出“ConverterNotFoundException”

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/49500309/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-12 03:01:29  来源:igfitidea点击:

Spring JPA native query with Projection gives "ConverterNotFoundException"

javaspringspring-data-jpaprojection

提问by nonzaprej

I'm using Spring JPA and I need to have a native query. With that query, I need to get only two fields from the table, so I'm trying to use Projections. It isn't working, this is the error I'm getting:

我正在使用 Spring JPA,我需要一个本机查询。使用该查询,我只需要从表中获取两个字段,因此我尝试使用Projections。它不起作用,这是我收到的错误:

org.springframework.core.convert.ConverterNotFoundException: No converter found capable of converting from type [org.springframework.data.jpa.repository.query.AbstractJpaQuery$TupleConverter$TupleBackedMap] to type [com.example.IdsOnly]

I tried to follow precisely the instructions of that page I linked, I tried to make my query non-native (do I actually need it to be native if I use projections, btw?), but I always get that error.
If I use an interface it works, but the results are proxies and I really need them to be "normal results" that I can turn into json.

我试图准确地遵循我链接的那个页面的说明,我试图使我的查询非本地(顺便说一句,如果我使用投影,我真的需要它是本地的吗?),但我总是得到那个错误。
如果我使用一个接口,它可以工作,但结果是代理,我真的需要它们是我可以变成 json 的“正常结果”。

So, here's my code. The Entity:

所以,这是我的代码。实体:

import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor
@Entity
@Table(name = "TestTable")
public class TestTable {

    @Id
    @Basic(optional = false)
    @GeneratedValue(strategy = GenerationType.SEQUENCE)
    @Column(name = "Id")
    private Integer id;
    @Column(name = "OtherId")
    private String otherId;
    @Column(name = "CreationDate")
    @Temporal(TemporalType.TIMESTAMP)
    private Date creationDate;
    @Column(name = "Type")
    private Integer type;
}

The class for the projection:

投影类:

import lombok.Value;

@Value // This annotation fills in the "hashCode" and "equals" methods, plus the all-arguments constructor
public class IdsOnly {

    private final Integer id;
    private final String otherId;
}

The Repository:

存储库:

public interface TestTableRepository extends JpaRepository<TestTable, Integer> {

    @Query(value = "select Id, OtherId from TestTable where CreationDate > ?1 and Type in (?2)", nativeQuery = true)
    public Collection<IdsOnly> findEntriesAfterDate(Date creationDate, List<Integer> types);
}

And the code that tries to get the data:

以及尝试获取数据的代码:

@Autowired
TestTableRepository ttRepo;
...
    Date theDate = ...
    List<Integer> theListOfTypes = ...
    ...
    Collection<IdsOnly> results = ttRepo.findEntriesAfterDate(theDate, theListOfTypes);  

Thanks for the help. I really don't understand what I'm doing wrong.

谢谢您的帮助。我真的不明白我做错了什么。

采纳答案by shahaf

with spring data you can cut the middle-man and simply define

使用弹簧数据,您可以减少中间人并简单地定义

public interface IdsOnly {
  Integer getId();
  String getOtherId();
}

and use a native query like;

并使用本机查询,如;

@Query(value = "Id, OtherId from TestTable where CreationDate > ?1 and Type in (?2)", nativeQuery = true)
    public Collection<IdsOnly> findEntriesAfterDate(Date creationDate, List<Integer> types);

check out https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#projections

查看https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#projections

回答by Robert Niestroj

The query should be using a constructor expression:

查询应该使用构造函数表达式

@Query("select new com.example.IdsOnly(t.id, t.otherId) from TestTable t where t.creationDate > ?1 and t.type in (?2)")

And i dont know Lombok, but make sure there is a constructor that takes the two IDs as parameters.

而且我不知道 Lombok,但请确保有一个将两个 ID 作为参数的构造函数。

回答by Montassar El Béhi

JPA 2.1 introduces an interesting ConstructorResultfeature if you want to keep it native.

JPA 2.1 引入了一个有趣的ConstructorResult特性,如果你想保持它的原生

回答by Madhura

You can return list of Object Array (List) as return type of the native query method in repository class.

您可以返回对象数组(列表)列表作为存储库类中本机查询方法的返回类型。

@Query(
            value = "SELECT [type],sum([cost]),[currency] FROM [CostDetails] " +
                    "where product_id = ? group by [type],[currency] ",
            nativeQuery = true
    )
    public List<Object[]> getCostDetailsByProduct(Long productId);
for(Object[] obj : objectList){
     String type = (String) obj[0];
     Double cost = (Double) obj[1];
     String currency = (String) obj[2];
     }