springboot?jpa?實(shí)現(xiàn)返回結(jié)果自定義查詢(xún)
jpa 返回結(jié)果自定義查詢(xún)
這里自定義的實(shí)體是沒(méi)有在數(shù)據(jù)映射的實(shí)體。可以返回聚合函數(shù)的值。(個(gè)人理解可以。。。。。。)
第一種方法
實(shí)體類(lèi)。(這里本人使用的是idea)
@Data
public class NameOnlyDto ? implements Serializable {
? ? private ?String ?firstName;
? ? private ?String ?lastName;
? ? private ?String ?sex ;
}repository類(lèi)(這里不是 使用的繼承jpa中的 的方式。而是使用的EntityManager)。代碼中有詳細(xì)的注釋。
@Repository
public class CustomEntity {
? ? // 實(shí)體管理器EntityManager是負(fù)責(zé)管理Entity的對(duì)象。對(duì)Entity的操作包括添加、刪除、修改和查詢(xún),都是通過(guò)實(shí)體管理器來(lái)實(shí)現(xiàn)的。
? ? @PersistenceContext
? ? private EntityManager entityManager;
?
? ? //EntityManagerFactory
?
? ? @Transactional
? ? public List<NameOnlyDto> listNameOnlyDto(){
? ? ? ? String sql = "select p.last_name lastName, p.first_name firstName from PERSON p";
? ? ? ? // hibernate 5.2 之前
? ? ? ? // SQLQuery sqlQuery = entityManager.createNativeQuery(sql).unwrap(NativeQueryImpl.class);
? ? ? ? // hibernate 5.2 之后的 寫(xiě)法
?
? ? ? ? // unwrap 讓JPA的Query返回Map對(duì)象 javax.persistence.Query.unwrap
? ? ? ? // hibernate 或jpa 中使用 AliasToBeanResultTransformer 自定義類(lèi)型轉(zhuǎn)換ResultTransformer 下劃線(xiàn)轉(zhuǎn)駝峰
? ? ? ? SQLQuery sqlQuery = entityManager.createNativeQuery(sql).unwrap(NativeQueryImpl.class);
? ? ? ? /*Query query =
? ? ? ? ? ? ? ? sqlQuery.setResultTransformer(Transformers.aliasToBean(NameOnlyDto.class));
? ? ? ? List<NameOnlyDto> list = query.getResultList();//.list();*/
?
? ? ? ? Query query =
? ? ? ? ? ? ? ? sqlQuery.setResultTransformer(Transformers.aliasToBean(NameOnlyDto.class));
?
? ? ? ? List<NameOnlyDto> ?list =query.getResultList();
? ? ? ? entityManager.clear();
? ? ? ? return list;
? ? }
}OK。就這樣就可以了。個(gè)人測(cè)試似乎在oracle數(shù)據(jù)庫(kù) 不行??赡苁莝ql查詢(xún)結(jié)果不太一樣
第二種方法
可以在特定的場(chǎng)合使用。
自定義類(lèi)
public class NameOnlyDtoT implements Serializable {
? ? private ?String ?firstName;
? ? private ?String ?lastName;
? ? // private ?String ?address;
? ? private ?String ?sex;
? ? //構(gòu)造函數(shù) 特殊注意 這里返回幾個(gè)字段就要有幾個(gè)字段的構(gòu)造參數(shù) 感覺(jué)不太合適的地方
? ? public NameOnlyDtoT(String firstName, String lastName) {
? ? ? ? this.firstName = firstName;
? ? ? ? this.lastName = lastName;
? ? }
? ?/* public NameOnlyDtoT(String firstName, String lastName, String sex) {
? ? ? ? this.firstName = firstName;
? ? ? ? this.lastName = lastName;
? ? ? ? this.sex = sex;
? ? }*/
}這里是repository中的寫(xiě)法
// 切記不能使用@query.如果使用@query 個(gè)人感覺(jué)和上面那種方法是一樣的邏輯
List<T> findByLastName(String lastname,Class<T> type);
? ? ? ? 使用(這里注意的是NameOnlyDtoT 中字段能賦值的只能是person中 含有的字段。這是個(gè)人覺(jué)得雞肋的存在)
? ? public ?List<NameOnlyDtoT> ?testNameOnlyDtoTS(){
? ? ? ? List<NameOnlyDtoT> ?nameOnlyDtoTS= personRepository.findByLastName("哈哈", NameOnlyDtoT.class);
? ? ? return nameOnlyDtoTS;
}使用jpa兩張表聯(lián)查返回自定義實(shí)體
在java開(kāi)發(fā)中,用Jpa框架做連表查詢(xún)時(shí)(需要返回兩張表的各自部分字段),在返回對(duì)象的過(guò)程中感覺(jué)比較棘手,一直沒(méi)有一個(gè)好的解決方案,網(wǎng)上也有各種版本的方法,下面的方法本人感覺(jué)最方便使用
1、創(chuàng)建一個(gè)SpringBoot空白項(xiàng)目,引入pom依賴(lài)
先看項(xiàng)目結(jié)構(gòu),為了簡(jiǎn)化,沒(méi)有引入service層,直接使用controller調(diào)用dao層

pom.xml配置
? ? ? ? <!-- web依賴(lài) --> ? ? ? ? <dependency> ? ? ? ? ? ? <groupId>org.springframework.boot</groupId> ? ? ? ? ? ? <artifactId>spring-boot-starter-web</artifactId> ? ? ? ? </dependency> ? ? ? ? <!-- ?lombok依賴(lài) --> ? ? ? ? <dependency> ? ? ? ? ? ? <groupId>org.projectlombok</groupId> ? ? ? ? ? ? <artifactId>lombok</artifactId> ? ? ? ? ? ? <version>1.18.8</version> ? ? ? ? </dependency> ? ? ? ? <!-- jpa依賴(lài) --> ? ? ? ? <dependency> ? ? ? ? ? ? <groupId>org.springframework.boot</groupId> ? ? ? ? ? ? <artifactId>spring-boot-starter-data-jpa</artifactId> ? ? ? ? </dependency> ? ? ? ? <!-- mysql依賴(lài) --> ? ? ? ? <dependency> ? ? ? ? ? ? <groupId>mysql</groupId> ? ? ? ? ? ? <artifactId>mysql-connector-java</artifactId> ? ? ? ? ? ? <scope>runtime</scope> ? ? ? ? </dependency>
2、application.yml配置文件
server: ? port: 13333 spring: ? datasource: ? ? url: jdbc:mysql://localhost:3306/test?characterEncoding=UTF-8&autoReconnect=true&serverTimezone=Asia/Shanghai&zeroDateTimeBehavior=convertToNull ? ? username: root ? ? password: 12345678 ? ? driver-class-name: com.mysql.jdbc.Driver ? jpa: ? ? show-sql: true ? ? hibernate: ? ? ? ddl-auto: none
3、數(shù)據(jù)庫(kù)(有兩張表user/address)

我們現(xiàn)在需要聯(lián)查user和address表,address表中的user_id是和user表中id是做關(guān)聯(lián)查詢(xún)
4、User.java 和 Address.java

5、UserDaoRepository.java 和 AddressDaoRepository.java

附上UserDaoRepository.java的代碼
package com.lss.jpa.dao;
import com.lss.jpa.entity.dto.UserAddressDto;
import com.lss.jpa.entity.po.User;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import java.util.List;
import java.util.Map;
public interface UserDaoRepository extends JpaRepository<User, Integer> {
? ? @Query(value = "select \"title\" as common, u.id as id, u.name as name, a.id as addressId, a.address as addressName from user u, address a where u.id = a.user_id", nativeQuery = true)
? ? public List<UserAddressDto> findAllUserAddress();
? ? @Query(value = "select \"title\" as common, u.id as id, u.name as name, a.id as addressId, a.address as addressName from user u, address a where u.id = a.user_id and u.id=1", nativeQuery = true)
? ? public UserAddressDto findAllUserAddressById();
? ? @Query(value = "select \"title\" as common, u.id as id, u.name as name, a.id as addressId, a.address as addressName from user u, address a where u.id = a.user_id and u.id=1", nativeQuery = true)
? ? public Map<String, Object> findAllUserAddressByMap();
}6、UserAddressDto.java代碼
package com.lss.jpa.entity.dto;
public interface UserAddressDto {
? ? Integer getId();
? ? String getName();
? ? String getAddressName();
? ? Integer getAddressId();
? ? String getCommon();
}此處我們自定義了UserAdressDto來(lái)接收兩張表返回的數(shù)據(jù),注意:此時(shí)創(chuàng)建的是一個(gè)interface,并且里面的字段是用get的形式創(chuàng)建的接收參數(shù)
7、TestController.java
package com.lss.jpa.web;
import com.lss.jpa.dao.UserDaoRepository;
import com.lss.jpa.entity.dto.UserAddressDto;
import com.lss.jpa.entity.po.User;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
import java.util.Map;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
@RestController
@Slf4j
public class TestController {
? ? @Autowired
? ? private UserDaoRepository userDaoRepository;
? ? @GetMapping("test")
? ? public String test(){
? ? ? ? List<UserAddressDto> all = userDaoRepository.findAllUserAddress();
? ? ? ? all.stream().forEach(dto -> {
? ? ? ? ? ? log.info("result: id:{}, name:{}, addressId:{}, addressName:{}, common:{}", dto.getId(), dto.getName(), dto.getAddressId(), dto.getAddressName(), dto.getCommon());
? ? ? ? });
? ? ? ? UserAddressDto dto = userDaoRepository.findAllUserAddressById();
? ? ? ? log.info("result: id:{}, name:{}, addressId:{}, addressName:{}, common:{}", dto.getId(), dto.getName(), dto.getAddressId(), dto.getAddressName(), dto.getCommon());
? ? ? ? Map<String, Object> map = userDaoRepository.findAllUserAddressByMap();
? ? ? ? log.info("map:{}", map);
? ? ? ? List<User> userList = userDaoRepository.findAll();
? ? ? ? log.info("userList:{}", userList);
? ? ? ? return "ok";
? ? }
}最后,啟動(dòng)項(xiàng)目,調(diào)用/test接口
curl http://localhost:13333/test
看console里打印結(jié)果
Hibernate: select "title" as common, u.id as id, u.name as name, a.id as addressId, a.address as addressName from user u, address a where u.id = a.user_id
2020-02-23 13:14:33.293 INFO 2816 --- [io-13333-exec-3] com.lss.jpa.web.TestController : result: id:1, name:zhangsan , addressId:1, addressName:beijing, common:title
2020-02-23 13:14:33.293 INFO 2816 --- [io-13333-exec-3] com.lss.jpa.web.TestController : result: id:2, name:lisi, addressId:2, addressName:tianjin, common:title
Hibernate: select "title" as common, u.id as id, u.name as name, a.id as addressId, a.address as addressName from user u, address a where u.id = a.user_id and u.id=1
2020-02-23 13:14:33.296 INFO 2816 --- [io-13333-exec-3] com.lss.jpa.web.TestController : result: id:1, name:zhangsan , addressId:1, addressName:beijing, common:title
Hibernate: select "title" as common, u.id as id, u.name as name, a.id as addressId, a.address as addressName from user u, address a where u.id = a.user_id and u.id=1
2020-02-23 13:14:33.299 INFO 2816 --- [io-13333-exec-3] com.lss.jpa.web.TestController : map:org.springframework.data.jpa.repository.query.AbstractJpaQuery$TupleConverter$TupleBackedMap@72cce81
Hibernate: select user0_.id as id1_1_, user0_.name as name2_1_ from user user0_
2020-02-23 13:14:33.305 INFO 2816 --- [io-13333-exec-3] com.lss.jpa.web.TestController : userList:[User(id=1, name=zhangsan ), User(id=2, name=lisi), User(id=3, name=wangwu), User(id=4, name=zhaoliu)]
我們可以拷到輸出的sql和聯(lián)查出來(lái)的數(shù)據(jù)結(jié)果,都被dto完美接收
特別注意,接收的dto一定要是interface,里面的參數(shù)要寫(xiě)成get形式的方法體,這樣jpa在查詢(xún)到數(shù)據(jù)后,會(huì)自動(dòng)映射到interface里,通過(guò)調(diào)用get的方法體相當(dāng)于調(diào)用了參數(shù)值,這樣就會(huì)把數(shù)據(jù)取出來(lái)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
用java實(shí)現(xiàn)學(xué)生信息管理系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)學(xué)生信息管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-09-09
java后臺(tái)驗(yàn)證碼生成的實(shí)現(xiàn)方法
在我們使用進(jìn)行系統(tǒng)開(kāi)發(fā)時(shí),為了提高系統(tǒng)的安全性,在登錄的時(shí)候多數(shù)人都會(huì)要求輸入驗(yàn)證,本文介紹了java后臺(tái)驗(yàn)證碼生成的實(shí)現(xiàn)方法,感興趣的一起來(lái)了解一下2021-05-05
Java實(shí)現(xiàn)簡(jiǎn)單LRU緩存機(jī)制的方法
這篇文章主要介紹了Java實(shí)現(xiàn)簡(jiǎn)單LRU緩存機(jī)制的方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-05-05
Java實(shí)現(xiàn)導(dǎo)出Word文檔的示例代碼
poi-tl是一個(gè)基于Apache POI的Word模板引擎,也是一個(gè)免費(fèi)開(kāi)源的Java類(lèi)庫(kù),你可以非常方便的加入到你的項(xiàng)目中。本文就利用它實(shí)現(xiàn)導(dǎo)出Word文檔功能,需要的可以參考一下2023-02-02
基于Spring boot @Value 注解注入屬性值的操作方法
這篇文章主要介紹了結(jié)合SpEL使用@Value-基于配置文件或非配置的文件的值注入-Spring Boot的相關(guān)知識(shí),本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-07-07
Spring處理@Async導(dǎo)致的循環(huán)依賴(lài)失敗問(wèn)題的方案詳解
這篇文章主要為大家詳細(xì)介紹了SpringBoot中的@Async導(dǎo)致循環(huán)依賴(lài)失敗的原因及其解決方案,文中的示例代碼講解詳細(xì),感興趣的可以學(xué)習(xí)一下2022-07-07
Java中不用第三個(gè)變量來(lái)互換兩個(gè)變量的值
在程序運(yùn)行期間,隨時(shí)可能產(chǎn)生一些臨時(shí)數(shù)據(jù),應(yīng)用程序會(huì)將這些數(shù)據(jù)保存在一些內(nèi)存單元中,每個(gè)內(nèi)存單元都用一個(gè)標(biāo)識(shí)符來(lái)標(biāo)識(shí)。這些內(nèi)存單元被稱(chēng)為變量,定義的標(biāo)識(shí)符就是變量名,內(nèi)存單元中存儲(chǔ)的數(shù)據(jù)就是變量的值2021-10-10
java中對(duì)象為null時(shí)的打印輸出方式
這篇文章主要介紹了java中對(duì)象為null時(shí)的打印輸出方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-09-09

