Mam metodę repozytorium Spring Data z natywnym zapytaniem
@Query(value = "SELECT g.*, gm.* FROM group g LEFT JOIN group_members gm ON g.group_id = gm.group_id and gm.user_id = :userId WHERE g.group_id = :groupId", nativeQuery = true)
GroupDetails getGroupDetails(@Param("userId") Integer userId, @Param("groupId") Integer groupId);
i chciałbym zmapować wynik do Non-Entity POJO GroupDetails
.
Czy jest to możliwe, a jeśli tak, czy mógłbyś podać przykład?
GroupDetails
oznaczyć@Entity
? Jeśli to możliwe, czy możesz powiedzieć, do której klasy@NamedNativeQuery
należy zastosować adnotację ?@SqlResultSetMapping
i@NamedNativeQuery
adnotacje muszą być obecne na encji używanej w Twoim repozytorium Spring Data (np.public interface CustomRepository extends CrudRepository<CustomEntity, Long>
to jestCustomEntity
klasa)Myślę, że najłatwiej to zrobić używając tzw. Projekcji. Może mapować wyniki zapytań do interfejsów. Używanie
SqlResultSetMapping
jest niewygodne i sprawia, że kod jest brzydki :).Przykład bezpośrednio z kodu źródłowego JPA danych sprężyny:
public interface UserRepository extends JpaRepository<User, Integer> { @Query(value = "SELECT firstname, lastname FROM SD_User WHERE id = ?1", nativeQuery = true) NameOnly findByNativeQuery(Integer id); public static interface NameOnly { String getFirstname(); String getLastname(); } }
Możesz również użyć tej metody, aby uzyskać listę prognoz.
Sprawdź ten wiosenny wpis w dokumentach JPA, aby uzyskać więcej informacji na temat prognoz.
Notatka 1:
Pamiętaj, aby mieć swoją
User
encję zdefiniowaną normalnie - pola z projektowanego interfejsu muszą być zgodne z polami w tej encji. W przeciwnym razie mapowanie pól może zostać uszkodzone (getFirstname()
może zwrócić wartość nazwiska i tak dalej).Uwaga 2:
Jeśli używasz
SELECT table.column ...
notacji, zawsze definiuj aliasy pasujące do nazw z encji. Na przykład ten kod nie będzie działał poprawnie (projekcja zwróci wartości null dla każdego gettera):@Query(value = "SELECT user.firstname, user.lastname FROM SD_User user WHERE id = ?1", nativeQuery = true) NameOnly findByNativeQuery(Integer id);
Ale to działa dobrze:
@Query(value = "SELECT user.firstname AS firstname, user.lastname AS lastname FROM SD_User user WHERE id = ?1", nativeQuery = true) NameOnly findByNativeQuery(Integer id);
W przypadku bardziej złożonych zapytań wolałbym zamiast tego używać
JdbcTemplate
niestandardowego repozytorium.źródło
JdbcTemplate
( docs.spring.io/spring-framework/docs/current/javadoc-api/org/… ). Możesz użyćgetClob
metody naresultSet
, aby pobrać clobInputStream
. Na przykład:rs.getClob("xml_column").getCharacterStream()
.Myślę, że podejście Michała jest lepsze. Ale jest jeszcze jeden sposób, aby uzyskać wynik z natywnego zapytania.
@Query(value = "SELECT g.*, gm.* FROM group g LEFT JOIN group_members gm ON g.group_id = gm.group_id and gm.user_id = :userId WHERE g.group_id = :groupId", nativeQuery = true) String[][] getGroupDetails(@Param("userId") Integer userId, @Param("groupId") Integer groupId);
Teraz możesz przekonwertować tę tablicę ciągów 2D na żądaną jednostkę.
źródło
Możesz napisać zapytanie natywne lub inne niż natywne tak, jak chcesz, a wyniki zapytania JPQL można opakować instancjami niestandardowych klas wyników. Utwórz DTO z tymi samymi nazwami kolumn zwróconych w zapytaniu i utwórz konstruktor zawierający wszystkie argumenty z taką samą sekwencją i nazwami, jakie zostały zwrócone przez zapytanie. Następnie użyj następującego sposobu, aby wysłać zapytanie do bazy danych.
@Query("SELECT NEW example.CountryAndCapital(c.name, c.capital.name) FROM Country AS c")
Utwórz DTO:
package example; public class CountryAndCapital { public String countryName; public String capitalName; public CountryAndCapital(String countryName, String capitalName) { this.countryName = countryName; this.capitalName = capitalName; } }
źródło
Możesz zrobić coś takiego
@NamedQuery(name="IssueDescriptor.findByIssueDescriptorId" , query=" select new com.test.live.dto.IssuesDto (idc.id, dep.department, iss.issueName, cat.issueCategory, idc.issueDescriptor, idc.description) from Department dep inner join dep.issues iss inner join iss.category cat inner join cat.issueDescriptor idc where idc.id in(?1)")
I musi być coś takiego jak Konstruktor
public IssuesDto(long id, String department, String issueName, String issueCategory, String issueDescriptor, String description) { super(); this.id = id; this.department = department; this.issueName = issueName; this.issueCategory = issueCategory; this.issueDescriptor = issueDescriptor; this.description = description; }
źródło
Na moim komputerze ten kod działa, trochę różni się od odpowiedzi Daimona.
źródło