springboot?jpa?實現(xiàn)返回結(jié)果自定義查詢
jpa 返回結(jié)果自定義查詢
這里自定義的實體是沒有在數(shù)據(jù)映射的實體??梢苑祷鼐酆虾瘮?shù)的值。(個人理解可以。。。。。。)
第一種方法
實體類。(這里本人使用的是idea)
@Data public class NameOnlyDto ? implements Serializable { ? ? private ?String ?firstName; ? ? private ?String ?lastName; ? ? private ?String ?sex ; }
repository類(這里不是 使用的繼承jpa中的 的方式。而是使用的EntityManager)。代碼中有詳細的注釋。
@Repository public class CustomEntity { ? ? // 實體管理器EntityManager是負責管理Entity的對象。對Entity的操作包括添加、刪除、修改和查詢,都是通過實體管理器來實現(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 之后的 寫法 ? ? ? ? ? // unwrap 讓JPA的Query返回Map對象 javax.persistence.Query.unwrap ? ? ? ? // hibernate 或jpa 中使用 AliasToBeanResultTransformer 自定義類型轉(zhuǎn)換ResultTransformer 下劃線轉(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。就這樣就可以了。個人測試似乎在oracle數(shù)據(jù)庫 不行??赡苁莝ql查詢結(jié)果不太一樣
第二種方法
可以在特定的場合使用。
自定義類
public class NameOnlyDtoT implements Serializable { ? ? private ?String ?firstName; ? ? private ?String ?lastName; ? ? // private ?String ?address; ? ? private ?String ?sex; ? ? //構(gòu)造函數(shù) 特殊注意 這里返回幾個字段就要有幾個字段的構(gòu)造參數(shù) 感覺不太合適的地方 ? ? 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中的寫法
// 切記不能使用@query.如果使用@query 個人感覺和上面那種方法是一樣的邏輯 List<T> findByLastName(String lastname,Class<T> type); ? ? ? ? 使用(這里注意的是NameOnlyDtoT 中字段能賦值的只能是person中 含有的字段。這是個人覺得雞肋的存在) ? ? public ?List<NameOnlyDtoT> ?testNameOnlyDtoTS(){ ? ? ? ? List<NameOnlyDtoT> ?nameOnlyDtoTS= personRepository.findByLastName("哈哈", NameOnlyDtoT.class); ? ? ? return nameOnlyDtoTS; }
使用jpa兩張表聯(lián)查返回自定義實體
在java開發(fā)中,用Jpa框架做連表查詢時(需要返回兩張表的各自部分字段),在返回對象的過程中感覺比較棘手,一直沒有一個好的解決方案,網(wǎng)上也有各種版本的方法,下面的方法本人感覺最方便使用
1、創(chuàng)建一個SpringBoot空白項目,引入pom依賴
先看項目結(jié)構(gòu),為了簡化,沒有引入service層,直接使用controller調(diào)用dao層
pom.xml配置
? ? ? ? <!-- web依賴 --> ? ? ? ? <dependency> ? ? ? ? ? ? <groupId>org.springframework.boot</groupId> ? ? ? ? ? ? <artifactId>spring-boot-starter-web</artifactId> ? ? ? ? </dependency> ? ? ? ? <!-- ?lombok依賴 --> ? ? ? ? <dependency> ? ? ? ? ? ? <groupId>org.projectlombok</groupId> ? ? ? ? ? ? <artifactId>lombok</artifactId> ? ? ? ? ? ? <version>1.18.8</version> ? ? ? ? </dependency> ? ? ? ? <!-- jpa依賴 --> ? ? ? ? <dependency> ? ? ? ? ? ? <groupId>org.springframework.boot</groupId> ? ? ? ? ? ? <artifactId>spring-boot-starter-data-jpa</artifactId> ? ? ? ? </dependency> ? ? ? ? <!-- mysql依賴 --> ? ? ? ? <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ù)庫(有兩張表user/address)
我們現(xiàn)在需要聯(lián)查user和address表,address表中的user_id是和user表中id是做關聯(liá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來接收兩張表返回的數(shù)據(jù),注意:此時創(chuàng)建的是一個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"; ? ? } }
最后,啟動項目,調(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)查出來的數(shù)據(jù)結(jié)果,都被dto完美接收
特別注意,接收的dto一定要是interface,里面的參數(shù)要寫成get形式的方法體,這樣jpa在查詢到數(shù)據(jù)后,會自動映射到interface里,通過調(diào)用get的方法體相當于調(diào)用了參數(shù)值,這樣就會把數(shù)據(jù)取出來
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關文章
基于Spring boot @Value 注解注入屬性值的操作方法
這篇文章主要介紹了結(jié)合SpEL使用@Value-基于配置文件或非配置的文件的值注入-Spring Boot的相關知識,本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-07-07Spring處理@Async導致的循環(huán)依賴失敗問題的方案詳解
這篇文章主要為大家詳細介紹了SpringBoot中的@Async導致循環(huán)依賴失敗的原因及其解決方案,文中的示例代碼講解詳細,感興趣的可以學習一下2022-07-07