Saya memiliki metode penyimpanan Data Musim Semi dengan kueri asli
@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);
dan saya ingin memetakan hasilnya ke POJO Non-Entitas GroupDetails
.
Apakah mungkin dan jika demikian, dapatkah Anda memberikan contoh?
GroupDetails
ditandai dengan@Entity
? Jika memungkinkan dapatkah Anda memberi tahu pada kelas mana anotasi@NamedNativeQuery
harus diterapkan?@SqlResultSetMapping
dan@NamedNativeQuery
anotasi harus ada pada entitas yang digunakan dalam penyimpanan Spring Data Anda (misalnya untukpublic interface CustomRepository extends CrudRepository<CustomEntity, Long>
itu adalahCustomEntity
kelas)Saya pikir cara termudah untuk melakukannya adalah dengan menggunakan apa yang disebut proyeksi. Itu dapat memetakan hasil kueri ke antarmuka. Menggunakan
SqlResultSetMapping
tidak nyaman dan membuat kode Anda jelek :).Contoh langsung dari kode sumber JPA data musim semi:
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(); } }
Anda juga dapat menggunakan metode ini untuk mendapatkan daftar proyeksi.
Lihat entri dokumen JPA data musim semi ini untuk info selengkapnya tentang proyeksi.
Catatan 1:
Ingatlah untuk
User
menetapkan entitas Anda seperti biasa - bidang dari antarmuka yang diproyeksikan harus cocok dengan bidang di entitas ini. Jika pemetaan lapangan mungkin rusak (getFirstname()
mungkin mengembalikan nilai nama belakang dan sebagainya).Catatan 2:
Jika Anda menggunakan
SELECT table.column ...
notasi, selalu tentukan alias yang cocok dengan nama dari entitas. Misalnya kode ini tidak akan berfungsi dengan baik (proyeksi akan mengembalikan null untuk setiap pengambil):@Query(value = "SELECT user.firstname, user.lastname FROM SD_User user WHERE id = ?1", nativeQuery = true) NameOnly findByNativeQuery(Integer id);
Tapi ini berfungsi dengan baik:
@Query(value = "SELECT user.firstname AS firstname, user.lastname AS lastname FROM SD_User user WHERE id = ?1", nativeQuery = true) NameOnly findByNativeQuery(Integer id);
Dalam kasus kueri yang lebih kompleks, saya lebih suka menggunakan
JdbcTemplate
repositori kustom sebagai gantinya.sumber
JdbcTemplate
( docs.spring.io/spring-framework/docs/current/javadoc-api/org/… ) sebagai gantinya. Anda dapat menggunakangetClob
metode onresultSet
untuk mengambil clobInputStream
. Untuk contoh:rs.getClob("xml_column").getCharacterStream()
.Saya pikir pendekatan Michal lebih baik. Namun, ada satu cara lagi untuk mendapatkan hasil dari kueri asli.
@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);
Sekarang, Anda dapat mengubah larik string 2D ini menjadi entitas yang Anda inginkan.
sumber
Anda dapat menulis kueri native atau non-native seperti yang Anda inginkan, dan Anda dapat menggabungkan hasil kueri JPQL dengan instance kelas hasil kustom. Buat DTO dengan nama kolom yang sama yang dikembalikan dalam kueri dan buat semua konstruktor argumen dengan urutan dan nama yang sama seperti yang dikembalikan oleh kueri. Kemudian gunakan cara berikut untuk membuat kueri database.
@Query("SELECT NEW example.CountryAndCapital(c.name, c.capital.name) FROM Country AS c")
Buat DTO:
package example; public class CountryAndCapital { public String countryName; public String capitalName; public CountryAndCapital(String countryName, String capitalName) { this.countryName = countryName; this.capitalName = capitalName; } }
sumber
Anda bisa melakukan sesuatu seperti
@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)")
Dan harus ada Constructor like
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; }
sumber
Di komputer saya, saya mendapatkan kode ini berfungsi. Ini sedikit berbeda dari jawaban Daimon.
sumber