最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

JPA如何使用nativequery多表關聯(lián)查詢返回自定義實體類

 更新時間:2021年11月18日 11:56:47   作者:lw5885799  
這篇文章主要介紹了JPA如何使用nativequery多表關聯(lián)查詢返回自定義實體類,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教

JPA nativequery多表關聯(lián)查詢返回自定義實體類

JPA官方推薦的多表關聯(lián)查詢使用不便,接觸的有些項目可能會使用JPA 做簡單查詢,Mybaits做復雜查詢。所以想要尋找一種好用的解決方案。

JPA多表關聯(lián)的實現(xiàn)方式

1.使用Specification實現(xiàn)映射關系匹配,如@ManyToOne等

2.使用NativeQuery等sql或hql來實現(xiàn)

優(yōu)缺點對比

1.映射關系是hibernate的入門基礎,很多人都會習慣去使用。個人不太喜歡這種方式,復用性太弱,且不靈活特別是在多表復雜業(yè)務情況下。

2.使用Specification方式需要繼承JpaSpecificationExecutor接口,構造對應的方法后傳入封裝查詢條件的Specification對象。邏輯上簡單易懂,但是構造Specification對象需要拼接格式條件非常繁瑣。

3.直接使用NativeQuery等方式實現(xiàn)復雜查詢個人比較喜歡,直觀且便利,弊端在于無法返回自定義實體類。需要手動封裝工具類來實現(xiàn)Object到目標對象的反射。

使用sql并返回自定義實體類

個人比較喜歡的實現(xiàn)方式,不多說看代碼

import org.springframework.stereotype.Repository;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.transaction.Transactional;
 
@Repository
public class EntityManagerDAO {
    @PersistenceContext
    private EntityManager entityManager;
     /**
     * 人員列表排序
     * @return
     */
    @Transactional
    public List<BackstageUserListDTO> listUser(){
        String sql = "select a.create_time createTime," +
                "a.mobilephone phoneNum," +
                "a.email email,a.uid uid," +
                "a.enabled enabled," +
                "c.id_number idNumber," +
                " (case b.`status` when 1 then 1 else 0 end) status " +
                "from tbl_sys_user a " +
                "LEFT JOIN user_high_qic b on a.uid=b.u_id" +
                "LEFT JOIN user_qic c on a.uid=c.uid " +
                "ORDER BY status desc";
 
        SQLQuery sqlQuery = entityManager.createNativeQuery(sql).unwrap(SQLQuery.class);
        Query query = 
     sqlQuery.setResultTransformer(Transformers.aliasToBean(BackstageUserListDTO.class));
        List<BackstageUserListDTO> list = query.list();
        entityManager.clear();
        return list;
    }
}
public class BackstageUserListDTO implements Serializable{
    private static final long serid = 1L;
    private String createTime;
    private String phoneNum;
    private String email;
    private BigInteger uid;
    private Integer enabled;
    private String idNumber;
    private BigInteger status;
    //GETTER SETTER
}

這樣一個需求如果使用前兩種方式實現(xiàn),無疑會非常麻煩。使用這種方式能夠直接反射需要的自定義實體類。

可以根據(jù)需求整理封裝成不同的方法,加入排序,分頁等。我在這里主要提供一種方便的解決思路。

JPA多表關聯(lián)動態(tài)查詢(自定義sql語句)

項目需求,查詢需求數(shù)據(jù)需要多表鏈接——>根據(jù)多種條件篩選查詢到的數(shù)據(jù),在網(wǎng)上查了很多資料最終選擇這個字符串拼接查詢

類似如此動態(tài)查詢

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-cA0h3Qnw-1590984326742)(../AppData/Roaming/Typora/typora-user-images/image-20200529152434229.png)]

以下是本人項目中使用總結:

實體類

/**
 * 訂單表
 */
@Entity
@Table(name = "signedorder")
@Getter
@Setter
@NoArgsConstructor
@EntityListeners(AuditingEntityListener.class)
public class SignedOrder {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column
    private Integer id;//id
    @CreatedDate
    @Column(updatable = false)
    private Date createTime;//創(chuàng)建時間
    @LastModifiedDate
    @Column
    private Date lastModifiedTime;//修改時間
    @ManyToOne(fetch = FetchType.EAGER, cascade = {
            CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REFRESH
    })
    @JoinTable(name = "staff_signedorder", joinColumns = @JoinColumn(name =
            "signedorder_id"), inverseJoinColumns = @JoinColumn(name = "staff_id"))
    private Staff staff;//所屬用戶
    @JoinColumn(name = "industry_id")
    private Integer industryId;//行業(yè)Id
}
/**
 * 用戶表
 */
@Entity
@Table(name = "staff")
@Getter
@Setter
@NoArgsConstructor
public class Staff {
 
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    private Integer id;//id
    @Column(name = "name", length = 25)
    private String name;//姓名
    @JoinColumn(name = "city_id")
    private Integer cityId;//城市id
/**
 * 城市表
 */
@Entity
@Table(name = "city")
@Getter
@Setter
@NoArgsConstructor
@Accessors(chain = true)
public class City {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    private Integer id;//id
    @Column(name = "name", length = 50)
    private String name;//名稱
}
//行業(yè)表和城市表一致,就不展示了

注解解釋

實體類中相關注解解釋:

  • @Entity: 對實體注釋。任何Hibernate映射對象都要有這個注釋
  • @Table: 聲明此對象映射到數(shù)據(jù)庫的數(shù)據(jù)表,該注釋不是必須的,如果沒有則系統(tǒng)使用默認值(實體的短類名)
  • @Getter @Setter、 @NoArgsConstructor:lombok提供注解,get、set方法及無參構造
  • @EntityListeners(AuditingEntityListener.class):加上此注解,時間注解@LastModifiedDate 和 @CreatedDate才可以生效
  • @Id: 聲明此屬性為主鍵
  • @GeneratedValue(strategy = GenerationType.IDENTITY):指定主鍵,

TABLE:使用一個特定的數(shù)據(jù)庫表格來保存主鍵;

IDENTITY:主鍵由數(shù)據(jù)庫自動生成(主要是自動增長型);

SEQUENCR:根據(jù)底層數(shù)據(jù)庫的序列來生成主鍵,條件是數(shù)據(jù)庫支持序列;

AUTO:主鍵由程序控制

  • @CreatedDate(updatable = false):創(chuàng)建時間時間字段,在insert的時候,會設置值;update時時間不變
  • @LastModifiedDate:修改時間段,update時會修改值
  • @ManyToOne(fetch = FetchType.EAGER, cascade = {CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REFRESH}): 多對一,

FetchType.EAGER:立即加載, 獲取關聯(lián)實體;

CascadeType.MERGE: 級聯(lián)更新;

CascadeType.PERSIST:級聯(lián)新建;

CascadeType.REFRESH:級聯(lián)刷新

  • @JoinTable: JoinColumn:保存關聯(lián)關系的外鍵的字段;inverseJoinColumns:保存關系的另外一個外鍵字
  • @Column:用來標識實體類中屬性與數(shù)據(jù)表中字段的對應關系

測試類

@RunWith(SpringRunner.class)
@SpringBootTest
public class SprinBootMarketingsystemApplicationTests {
    @PersistenceContext//jpa的數(shù)據(jù)庫操作類
    private EntityManager entityManger;
    @Test
    public void queryDb(){
       //給參數(shù)賦值
        Integer cityId = 1;
        Integer industryId = 2;
        Integer staffId = 16;
        Date startTime = DateUtil.parse("1970-01-01");//字符串時間轉換為date類型
        Date endTime = Calendar.getInstance().getTime();//獲取系統(tǒng)當前時間裝換為date類型
        
        //創(chuàng)建SQL語句主體
        StringBuffer stringBuffer = new StringBuffer("\tSELECT\n" +
                "\tcount( * ) count,\n" +
                "\tci.NAME cityName\n" +
                "\tFROM\n" +
                "\tsignedorder s\n" +
                "\tLEFT JOIN staff_signedorder t ON s.id = t.signedorder_id\n" +
                "\tLEFT JOIN staff sta ON t.staff_id = sta.id\n" +
                "\tLEFT JOIN city ci ON sta.city_id = ci.id\n" +
                "\tWHERE\n" +
                "\t1 = 1");
         Map<String,Object> map =  new HashMap<>();
         //拼接動態(tài)參數(shù)
        if(industryId != null){
            
             /*第一種給參數(shù)賦值方式
             1代表傳進來的參數(shù)順序,給參數(shù)賦值nativeQuery.setParameter(1, industryId);
             stringBuffer.append(" and s.industryId = ?1");*/
             //industryId代表傳進來的參數(shù)名稱,給參數(shù)賦值nativeQuery.setParameter("industryId", industryId);
             stringBuffer.append(" and s.industry_id = :industryId");
             map.put("industryId",industryId);
        }
        if(cityId != null){
            stringBuffer.append(" and ci.id = :cityId");
            map.put("cityId",cityId);
        }
        if(staffId != null){
            stringBuffer.append(" and sta.id = :staffId");
            map.put("staffId",staffId);
        }
        if(startTime!=null && endTime!=null){
            //使用這種賦值方式,時間類型需要給三個參數(shù),參數(shù)名稱,參數(shù)值,特定映射的類型TemporalType.DATE
            //nativeQuery.setParameter("create_time", startTime,TemporalType.DATE);
            stringBuffer.append( " and s.create_time BETWEEN :startTime and :endTime ");
            map.put("startTime",startTime);
            map.put("endTime",endTime);
        }
        Query nativeQuery = entityManger.createNativeQuery(stringBuffer.toString());
        for (String key : map.keySet()) {
            nativeQuery.setParameter(key, map.get(key));
        }
        //三種接受返回結果方式(第一種方式)
        /*nativeQuery.unwrap(SQLQuery.class).setResultTransformer(Transformers.TO_LIST);
        List resultList1 = nativeQuery.getResultList();
        for (Object o : resultList1) {
            System.out.println(o.toString());
        }*/
       //第二種方式和第一種方式相似
        /*nativeQuery.unwrap(SQLQuery.class).setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
        List<Map<String, Object>> resultList = nativeQuery.getResultList();
        for (Map<String, Object> map1 :resultList
        ) {
            System.out.println(map1);
        }*/
        //第三種方式:實體類接受
        nativeQuery.unwrap(SQLQuery.class).setResultTransformer(Transformers.aliasToBean(TestVo.class));
        List<TestVo> resultList = nativeQuery.getResultList();
        for (TestVo svo:resultList
        ) {
            System.out.println(svo.toString());
        }
    }

打印結果

第一種方式打印結果

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-iB3CVBpD-1590984326744)(ceshi1.png)]

第二種方式打印結果

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-lHOgQW55-1590984326745)(ceshi2.png)]

第三種方式打印結果

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-JTMsc780-1590984326747)(ceshi3.png)]

TestVo實體接收類

@Data
public class TestVo {
    private String cityName;//城市名字
    private BigInteger count;//簽單數(shù)量(必須使用BigInteger類型接受)
}

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關文章

  • JAVA隨機數(shù)隨機字母的實現(xiàn)(微信搶紅包小練習)

    JAVA隨機數(shù)隨機字母的實現(xiàn)(微信搶紅包小練習)

    這篇文章主要介紹了JAVA隨機數(shù)隨機字母的實現(xiàn)(微信搶紅包小練習),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-04-04
  • Spring Boot Debug調試過程圖解

    Spring Boot Debug調試過程圖解

    這篇文章主要介紹了Spring Boot Debug調試過程圖解,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-01-01
  • Spring中的依賴注入DI詳解

    Spring中的依賴注入DI詳解

    這篇文章主要介紹了Spring中的依賴注入DI詳解,組件之間依賴關系由容器在運行期決定,形象的說,即由容器動態(tài)的將依賴關系注入到組件之中,依賴注入的目的并非為軟件系統(tǒng)帶來更多功能,是為了提升組件重用的頻率,并為系統(tǒng)搭建一個靈活、可擴展的平臺,需要的朋友可以參考下
    2024-01-01
  • java 中RSA的方式實現(xiàn)非對稱加密的實例

    java 中RSA的方式實現(xiàn)非對稱加密的實例

    這篇文章主要介紹了java 中RSA的方式實現(xiàn)非對稱加密的實例的相關資料,這里提供實例幫助大家理解這部分知識,需要的朋友可以參考下
    2017-08-08
  • Java通過匿名類來實現(xiàn)回調函數(shù)實例總結

    Java通過匿名類來實現(xiàn)回調函數(shù)實例總結

    這篇文章主要介紹了Java通過匿名類來實現(xiàn)回調函數(shù)的例子,回調函數(shù)就是一種函數(shù)簽名(若干個輸入?yún)?shù)、一個輸出參數(shù))的規(guī)范,java雖不存在函數(shù)聲明,但是java可以用接口來強制規(guī)范。具體操作步驟大家可查看下文的詳細講解,感興趣的小伙伴們可以參考一下。
    2017-08-08
  • SpringCloud配置動態(tài)更新原理解析

    SpringCloud配置動態(tài)更新原理解析

    在微服務架構的浩瀚星海中,服務配置的動態(tài)更新如同魔法一般,能夠讓應用在不重啟的情況下,實時響應配置的變更,Spring Cloud作為微服務架構中的佼佼者,其動態(tài)配置更新的能力尤為引人注目,本文給大家介紹了SpringCloud配置動態(tài)更新原理,需要的朋友可以參考下
    2025-01-01
  • Mybatis使用命令生成逆向工程的方法

    Mybatis使用命令生成逆向工程的方法

    這篇文章主要介紹了Mybatis使用命令生成逆向工程的方法,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-01-01
  • Mybatis-Plus的SQL語句組拼原理說明

    Mybatis-Plus的SQL語句組拼原理說明

    這篇文章主要介紹了Mybatis-Plus的SQL語句組拼原理說明,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-06-06
  • 一文帶你揭秘SpringMvc參數(shù)值映射

    一文帶你揭秘SpringMvc參數(shù)值映射

    這篇文章主要給大家介紹了關于SpringMvc參數(shù)值映射的相關資料,文中通過實例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2022-01-01
  • Mybatis plus枚舉處理器的具體使用

    Mybatis plus枚舉處理器的具體使用

    在開發(fā)中,數(shù)據(jù)庫表中的字段很常見會使用枚舉類型來表示一些固定的取值范圍,本文主要介紹了Mybatis plus枚舉處理器的具體使用,具有一定的參考價值,感興趣的可以了解一下
    2024-03-03

最新評論

崇仁县| 临夏市| 五华县| 新河县| 松潘县| 洛川县| 南安市| 东山县| 镶黄旗| 炎陵县| 德安县| 永济市| 大足县| 邢台市| 辉南县| 永泰县| 东兰县| 沂水县| 沅江市| 泸西县| 唐海县| 钟祥市| 保定市| 和静县| 阜阳市| 武安市| 兴和县| 离岛区| 屏东县| 清丰县| 山东省| 临邑县| 乌鲁木齐县| 宜都市| 岗巴县| 如皋市| 海阳市| 英吉沙县| 西平县| 浦北县| 谷城县|