web-dev-qa-db-de.com

Native Spring-JPA-Abfrage mit Projektion gibt "ConverterNotFoundException" aus

Ich verwende Spring JPA und brauche eine native Abfrage. Mit dieser Abfrage brauche ich nur zwei Felder aus der Tabelle, also versuche ich Projections zu verwenden. Es funktioniert nicht, das ist der Fehler, den ich bekomme: 

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]

Ich habe versucht, den Anweisungen der verlinkten Seite genau zu folgen, ich habe versucht, meine Abfrage als nicht-systemeigen zu definieren (brauche ich sie eigentlich als native, wenn ich Projektionen verwende, übrigens?), Aber ich erhalte diesen Fehler immer.
Wenn ich ein Interface benutze, funktioniert es, aber die Ergebnisse sind Proxies und ich brauche sie wirklich, um "normale Ergebnisse" zu sein, die ich in Json verwandeln kann. 

Also hier ist mein Code. Die Entität: 

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;
}

Die Klasse für die Projektion: 

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;
}

Das 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);
}

Und der Code, der versucht, die Daten abzurufen: 

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

Danke für die Hilfe. Ich verstehe wirklich nicht, was ich falsch mache.

4
nonzaprej

Die Abfrage sollte einen Konstruktorausdruck verwenden :

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

Und ich kenne Lombok nicht, aber stellen Sie sicher, dass es einen Konstruktor gibt, der die beiden IDs als Parameter verwendet.

7
Robert Niestroj

JPA 2.1 führt eine interessante ConstructorResult - Funktion ein, wenn Sie native beibehalten möchten. 

3

mit frühlingsdaten kannst du den middle-man abschneiden und einfach verwenden

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

und verwenden Sie eine native Abfrage wie;

@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

2
shahaf

Sie können die Liste des Objektarrays (Liste) als Rückgabetyp der systemeigenen Abfragemethode in der Repository-Klasse zurückgeben.

@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];
     }
1
Madhura

Ich muss Werte aus 2 Tabellen zuordnen und so in der Repository-Datei lösen

@Query("select distinct emp.user.id as id, " +
    "concat(emp.user.firstName, ' ',emp.user.lastName, ' ',emp.extensionNumber) as name from NmsEmployee emp " +
    " where emp.domain.id = :domainId and (emp.activeUntil= null or emp.activeUntil > :lLogin) ")
    List<Selectable> getSelcByDomainId( @Param("domainId") Long domainId, @Param("lLogin") ZonedDateTime lLogin);

Wo wählbar ist

public interface Selectable {
     Long getId();
     String getName();
}
0
Inês Gomes