溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

怎么在JPA中自定義對(duì)象接收查詢結(jié)果集

發(fā)布時(shí)間:2021-01-30 14:03:13 來源:億速云 閱讀:698 作者:Leah 欄目:開發(fā)技術(shù)

本篇文章給大家分享的是有關(guān)怎么在JPA中自定義對(duì)象接收查詢結(jié)果集,小編覺得挺實(shí)用的,因此分享給大家學(xué)習(xí),希望大家閱讀完這篇文章后可以有所收獲,話不多說,跟著小編一起來看看吧。

class Person { 
 @Id UUID id;
 String firstname, lastname;
 Address address; 
 static class Address {
 String zipCode, city, street;
 }
} 
interface PersonRepository extends Repository<Person, UUID> { 
 Collection<Person> findByLastname(String lastname);
}

自定義對(duì)象接收查詢結(jié)果集方法如下:

(1)增加接收數(shù)據(jù)接口

interface NamesOnly { 
 String getFirstname();
 String getLastname();
}

(2)增加持久層接口

interface PersonRepository extends Repository<Person, UUID> { 
 Collection<NamesOnly> findByLastname(String lastname);
}

如果要對(duì)查詢結(jié)果進(jìn)行序列號(hào)的話就會(huì)有點(diǎn)問題:

{
 "errorCode": "00",
 "errorMessage": "操作成功",
 "returnObject": [
 {
  "createtime": 1526358195000,
  "id": 49,
  "lastupdatetime": 1526358195000,
  "status": "2",
  "target": {
  "createtime": 1526358195000,
  "lastupdatetime": 1526358195000,
  "check_Wicket": "1",
  "facility_name": "血壓測(cè)量",
  "facility_Num": "C3",
  "id": 49,
  "status": "2",
  "check_name": "小湯154",
  "check_Num": "BY185201805140001"
  },
  "targetClass": "org.springframework.data.jpa.repository.query.AbstractJpaQuery$TupleConverter$TupleBackedMap"
 }
 ]
}

會(huì)出現(xiàn)targetClass這個(gè)字段,不能直接把結(jié)果拿來用,很惡心,又不想寫代碼中轉(zhuǎn)下。

經(jīng)過后來的摸索,其實(shí)如果只是為了返回JSON,也可以直接在Repository層直接用List<Map<String,Object>>來返回,

Map<String,Object>對(duì)應(yīng)單條查詢結(jié)果,完美解決序列化問題。

完畢。就這么簡(jiǎn)單。

補(bǔ)充:SpringBoot JPA查詢結(jié)果映射到自定義實(shí)體類

場(chǎng)景

舉一個(gè)簡(jiǎn)單的例子:

比如有一個(gè)Position實(shí)體類

@Entity
@Table(name = "position")
public class Position implements Serializable {
 private static final long serialVersionUID = 768016840645708589L;
 @Id
 @GeneratedValue(strategy = GenerationType.IDENTITY)
 private Long id;
 private String name;
 private BigDecimal salary;
 private String city;
 
 ...//省略getset方法
 ...//省略toString方法 
}

然后有一個(gè)PositionDetail實(shí)體類

@Entity
@Table(name = "position_detail")
public class PositionDetail implements Serializable {
 private static final long serialVersionUID = 4556211410083251360L;
 @Id
 @GeneratedValue(strategy = GenerationType.IDENTITY)
 private Long id;
 private Long pid;
 private String description;
 
 ...//省略getset方法
 ...//省略toString方法 
}

需求:

查詢職位基本信息,職位描述,因?yàn)樯婕暗絻蓮埍聿僮?,?jiǎn)單的查詢并不能滿足我們的需求,因此就需要自定義查詢接口并返回符合需求的結(jié)果。

接下來再定義一個(gè)實(shí)體類,用來接收查詢結(jié)果

public class PositionDO {
 private Long id;
 private String name;
 private BigDecimal salary;
 private String city;
 private String description;
 public PositionDO(Long id, String name, BigDecimal salary, String city, String description) {
 this.id = id;
 this.name = name;
 this.salary = salary;
 this.city = city;
 this.description = description;
 }
 ...//省略getset方法
 ...//省略toString方法 
}

編寫Dao接口,用來實(shí)現(xiàn)CRUD操作

public interface PositionDao extends JpaRepository<Position, Long> {
 @Query(nativeQuery = true, value = "select t1.id, t1.name, t1.salary, t1.city, t2.description) \n" +
 "from position t1 left join position_detail t2 on t1.id = t2.pid \n" +
 "where t1.id = :id")
 PositionDO findPositionById(@Param("id") Long id);
}

思考:

如果這樣寫會(huì)不會(huì)出現(xiàn)問題?接下來我們編寫一個(gè)測(cè)試類測(cè)試一下。

@SpringBootTest(classes = ShardingApplication.class)
@RunWith(SpringRunner.class)
public class TestShardingDatabase {
 @Resource
 PositionDao positionDao;
 @Test
 public void testQueryById() throws Exception{
 PositionDO positionDO = positionDao.findPositionById(548083053407240192L);
 System.out.println(positionDO);
 }
}

哈哈,翻車了吧,還好先測(cè)試了一波,問題不大。

Hibernate: select t1.id, t1.name, t1.salary, t1.city, t2.description 
from position t1 left join position_detail t2 on t1.id = t2.pid 
where t1.id = ?
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.lsp.dto.PositionDO]

分析原因:

那么到底是為什么造成這樣的原因呢?相信小伙伴們一眼就能看出來了,是因?yàn)镴pa找不到能夠從類型轉(zhuǎn)換的轉(zhuǎn)換器,而拋出這樣的異常。

現(xiàn)在問題來了,既然這樣不行,那么我們想要實(shí)現(xiàn)映射到自定義結(jié)果集該如何實(shí)現(xiàn)呢?

實(shí)現(xiàn):

JPA可以自定義SQL語句進(jìn)行查詢,然后查詢語句可以通過原生SQL語句(原生SQL語句也就是在@Query注解里加上nativeQuery = true)進(jìn)行查詢。當(dāng)然了,也可以通過JPQL進(jìn)行查詢。

我們這里就是通過JPQL進(jìn)行查詢,它的特征就是與原生SQL語句類似,完全面向?qū)ο?,通過類名和屬性訪問,而不是表名和表屬性。

由此PositionDao修改之后就像這樣

public interface PositionDao extends JpaRepository<Position, Long> {
 @Query(value = "select new com.lsp.domain.PositionDO(t1.id, t1.name, t1.salary, t1.city, t2.description) \n" +
  "from Position t1 left join PositionDetail t2 on t1.id = t2.pid \n" +
  "where t1.id = :id")
 PositionDO findPositionById(@Param("id") Long id);
}

接下來我們?cè)龠\(yùn)行測(cè)試方法看一下。

Hibernate: select position0_.id as col_0_0_, position0_.name as col_1_0_, position0_.salary as col_2_0_, position0_.city as col_3_0_, positionde1_.description as col_4_0_ from position position0_ left outer join position_detail positionde1_ on (position0_.id=positionde1_.pid) where position0_.id=?
PositionDO{id=548083053407240192, name='Jerry5', salary=10000.00, city='beijing5', description='this is message 5'}

以上就是怎么在JPA中自定義對(duì)象接收查詢結(jié)果集,小編相信有部分知識(shí)點(diǎn)可能是我們?nèi)粘9ぷ鲿?huì)見到或用到的。希望你能通過這篇文章學(xué)到更多知識(shí)。更多詳情敬請(qǐng)關(guān)注億速云行業(yè)資訊頻道。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

jpa
AI