欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Spring data JPA只查詢部分字段問題及解決

 更新時間:2024年08月12日 09:35:03   作者:北極象  
這篇文章主要介紹了Spring data JPA只查詢部分字段問題及解決,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教

背景

在JPA查詢中,有時只需要查部分字段,這時jpa repository查出的是map,無法映射到Entity類。

會提示錯誤:

org.springframework.core.convert.ConverterNotFoundException: 
No converter found capable of converting from type 
[org.springframework.data.jpa.repository.query.AbstractJpaQuery$TupleConverter$TupleBackedMap] to type

網(wǎng)上搜索有多種解決方案。這里列舉一下。

經(jīng)過驗證,本人采取了第一種方案,證明是可行的。

JPA 2.1以上的解決辦法

實體中增加named query和result map

@SqlResultSetMapping(name = "EBookInfo",
        classes = @ConstructorResult(targetClass = EBookInfo.class,
                columns = {
                        @ColumnResult(name = "book_id", type = Long.class),
                        @ColumnResult(name = "book_name", type = String.class),
                        @ColumnResult(name = "file_type", type = String.class)
                }))
@NamedNativeQuery(name = "listExpressEbooks",
        query = "select book_id, book_name, file_type from ebook order by update_date desc",
        resultSetMapping = "EBookInfo")
@Entity
@Table(name = "ebook")
public class Ebook {

    private Long bookId;

    private Integer authorId;
    private String authorName;
    private Integer categoryId;
    private String bookName;
    private String subTitle;
    private String tags;
    private String isbn;
    private String edition;
    private Byte bookType;
    private Integer star;
    private Integer downloadCount;
    private Byte status;
    private String fileType;
    private String outline;
    private String introduction;
    private String preface;
    private String cover;
    private Float price;
    private String publisher;
    private String bgColor;
    private String foreColor;
    private String titleColor;
    private String coverBackgroundId;
    private String coverPictureId;
    private Integer coverTemplateId;
    private String coverPictureMode;
    private Integer pageMode;
    private Timestamp requestDate;
    private Timestamp publishDate;
    private Timestamp updateDate;

定義一個新的DTO對象

字段和查詢的字段對應(yīng),需要提供構(gòu)造函數(shù):

@Data
public class EBookInfo {
    private Long bookId;
    private String bookName;    
    private String fileType;

    public EBookInfo(Long bookId, String bookName, String fileType) {
        this.bookId = bookId;
        this.bookName = bookName;
        this.fileType = fileType;
    }

}

repository中定義查詢接口

    @Query(name = "listExpressEbooks", nativeQuery = true)
    public List<EBookInfo> listExpressEbooks();

其它方案

查詢中構(gòu)造新對象

public List<Blog> selectByYearMonth(String year, String month, int status) {
    String sql = String.format("select new Blog(blog.id, blog.title, blog.abs, blog.createtime) from Blog blog where blog.status = %d and YEAR(createtime) = %s and MONTH(createtime) = %s order by blog.createtime desc", status, year, month);

    //Query query = this.em.createNativeQuery(sql, "ExpressedResult");
    Query query = this.em.createQuery(sql);
    List results = query.getResultList();

    return results;
}

上述方法是之前我項目中代碼庫里的寫法,Blog需要提供相應(yīng)的構(gòu)造函數(shù)。

自己寫convertor

repository 返回 Tuple 對象,自己寫代碼手動轉(zhuǎn)換為指定對象,repository層使用native查詢。

這里要借助輔助類:

class NativeResultProcessUtils {

        /**
         * tuple轉(zhuǎn)實體對象
         * @param source tuple對象
         * @param targetClass 目標(biāo)實體class
         * @param <T> 目標(biāo)實體類型
         * @return 目標(biāo)實體
         */
        public static <T> T processResult(Tuple source,Class<T> targetClass) {
            Object instantiate = BeanUtils.instantiate(targetClass);
            convertTupleToBean(source,instantiate,null);
            return (T) instantiate;
        }

        /**
         *
         * tuple轉(zhuǎn)實體對象
         * @param source tuple對象
         * @param targetClass 目標(biāo)實體class
         * @param <T> 目標(biāo)實體類型
         * @param ignoreProperties 要忽略的屬性
         * @return 目標(biāo)實體
         */
        public static <T> T processResult(Tuple source,Class<T> targetClass,String... ignoreProperties) {
            Object instantiate = BeanUtils.instantiate(targetClass);
            convertTupleToBean(source,instantiate,ignoreProperties);
            return (T) instantiate;
        }

        /**
         * 把tuple中屬性名相同的值復(fù)制到實體中
         * @param source tuple對象
         * @param target 目標(biāo)對象實例
         */
        public static void convertTupleToBean(Tuple source,Object target){
            convertTupleToBean(source,target,null);
        }

        /**
         * 把tuple中屬性名相同的值復(fù)制到實體中
         * @param source tuple對象
         * @param target 目標(biāo)對象實例
         * @param ignoreProperties 要忽略的屬性
         */
        public static void convertTupleToBean(Tuple source,Object target, String... ignoreProperties){
            //目標(biāo)class
            Class<?> actualEditable = target.getClass();
            //獲取目標(biāo)類的屬性信息
            PropertyDescriptor[] targetPds = BeanUtils.getPropertyDescriptors(actualEditable);
            //忽略列表
            List<String> ignoreList = (ignoreProperties != null ? Arrays.asList(ignoreProperties) : null);

            //遍歷屬性節(jié)點信息
            for (PropertyDescriptor targetPd : targetPds) {
                //獲取set方法
                Method writeMethod = targetPd.getWriteMethod();
                //判斷字段是否可以set
                if (writeMethod != null && (ignoreList == null || !ignoreList.contains(targetPd.getName()))) {
                    //獲取source節(jié)點對應(yīng)的屬性
                    String propertyName = targetPd.getName();
                    Object value = source.get(propertyName);
                    if(value!=null && ClassUtils.isAssignable(writeMethod.getParameterTypes()[0], value.getClass())) {
                        try {
                            //判斷target屬性是否private
                            if (!Modifier.isPublic(writeMethod.getDeclaringClass().getModifiers())) {
                                writeMethod.setAccessible(true);
                            }
                            //寫入target
                            writeMethod.invoke(target, value);
                        }
                        catch (Throwable ex) {
                            throw new FatalBeanException(
                                "Could not copy property '" + targetPd.getName() + "' from source to target", ex);
                        }
                    }
                }
            }
        }

    }

使用entityManager的Transformers.aliasToBean

未驗證,Spring data jpa未必支持

使用entityManager的Transforms.ALIAS_TO_ENTITY_MAP

未驗證

總結(jié)

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

相關(guān)文章

  • 基于Java8 Stream API實現(xiàn)數(shù)據(jù)抽取收集

    基于Java8 Stream API實現(xiàn)數(shù)據(jù)抽取收集

    這篇文章主要介紹了基于Java8 Stream API實現(xiàn)數(shù)據(jù)抽取收集,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-03-03
  • java獲取昨天日期字符串的方法

    java獲取昨天日期字符串的方法

    這篇文章主要介紹了java獲取昨天日期字符串的方法,涉及java針對日期與時間的運算與轉(zhuǎn)換等相關(guān)操作技巧,需要的朋友可以參考下
    2016-08-08
  • 一篇文章帶你詳解Spring的概述

    一篇文章帶你詳解Spring的概述

    這篇文章主要為大家介紹了Spring的概述,具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2022-01-01
  • SpringCloud+SpringBoot項目搭建結(jié)構(gòu)層次的實例

    SpringCloud+SpringBoot項目搭建結(jié)構(gòu)層次的實例

    這篇文章詳細(xì)介紹了SpringCloud項目的架構(gòu)層次及其搭建經(jīng)驗,包括Controller層、Service層、Repository層、Entity層、DTO層、Exception層等,通過文字和圖片的形式,幫助讀者理解如何組織和實現(xiàn)一個SpringBoot項目的不同層次
    2025-01-01
  • Java通過匿名類來實現(xiàn)回調(diào)函數(shù)實例總結(jié)

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

    這篇文章主要介紹了Java通過匿名類來實現(xiàn)回調(diào)函數(shù)的例子,回調(diào)函數(shù)就是一種函數(shù)簽名(若干個輸入?yún)?shù)、一個輸出參數(shù))的規(guī)范,java雖不存在函數(shù)聲明,但是java可以用接口來強制規(guī)范。具體操作步驟大家可查看下文的詳細(xì)講解,感興趣的小伙伴們可以參考一下。
    2017-08-08
  • MyBatis-Plus標(biāo)簽@TableField之fill自動填充方式

    MyBatis-Plus標(biāo)簽@TableField之fill自動填充方式

    這篇文章主要介紹了MyBatis-Plus標(biāo)簽@TableField之fill自動填充方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-06-06
  • Eclipse+Maven構(gòu)建Hadoop項目的方法步驟

    Eclipse+Maven構(gòu)建Hadoop項目的方法步驟

    這篇文章主要介紹了Eclipse+Maven構(gòu)建Hadoop項目的方法步驟,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-02-02
  • SpringCloud Gateway使用詳解

    SpringCloud Gateway使用詳解

    Spring Cloud Gateway是一個基于Spring Boot 2.x和Spring WebFlux的API網(wǎng)關(guān),可以幫助我們構(gòu)建微服務(wù)架構(gòu)中的統(tǒng)一入口。感興趣的同學(xué)可以參考一下
    2023-04-04
  • Java:DocumentBuilderFactory調(diào)用XML的方法實例

    Java:DocumentBuilderFactory調(diào)用XML的方法實例

    Java:DocumentBuilderFactory調(diào)用XML的方法實例,需要的朋友可以參考一下
    2013-04-04
  • springboot解析自定義yml方式

    springboot解析自定義yml方式

    這篇文章主要介紹了springboot解析自定義yml方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-08-08

最新評論