中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

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

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

如何使用JPA自定義VO類型轉換

發布時間:2021-11-22 13:36:20 來源:億速云 閱讀:161 作者:小新 欄目:開發技術

這篇文章主要介紹如何使用JPA自定義VO類型轉換,文中介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們一定要看完!

JPA自定義VO類型轉換(EntityUtils工具類)

在JPA查詢中,如果需要返回自定義的類,可以使用EntityUtils工具類,該類源碼:

import org.slf4j.Logger;
import org.slf4j.LoggerFactory; 
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
 
/**
 * @author 954L
 * @create 2019/10/30 17:27
 */
public class EntityUtils {
 
    private static final Logger log = LoggerFactory.getLogger(EntityUtils.class);
 
    /**
     * 將數組數據轉換為實體類
     * 此處數組元素的順序必須與實體類構造函數中的屬性順序一致
     *
     * @param list  數組對象集合
     * @param clazz 實體類
     * @param <T>   實體類
     * @param model 實例化的實體類
     * @return 實體類集合
     */
    public static <T> List<T> castEntity(List<Object[]> list, Class<T> clazz, Object model) {
        List<T> returnList = new ArrayList<T>();
        if (list.isEmpty()) return returnList;
        Object[] co = list.get(0);
        List<Map> attributeInfoList = getFiledsInfo(model);
        Class[] c2 = new Class[attributeInfoList.size()];
        if (attributeInfoList.size() != co.length) {
            return returnList;
        }
        for (int i = 0; i < attributeInfoList.size(); i++) {
            c2[i] = (Class) attributeInfoList.get(i).get("type");
        }
        try {
            for (Object[] o : list) {
                Constructor<T> constructor = clazz.getConstructor(c2);
                returnList.add(constructor.newInstance(o));
            }
        } catch (Exception ex) {
            log.error("實體數據轉化為實體類發生異常:異常信息:{}", ex.getMessage());
            return returnList;
        }
        return returnList;
    }
 
    private static Object getFieldValueByName(String fieldName, Object modle) {
        try {
            String firstLetter = fieldName.substring(0, 1).toUpperCase();
            String getter = "get" + firstLetter + fieldName.substring(1);
            Method method = modle.getClass().getMethod(getter, new Class[]{});
            Object value = method.invoke(modle, new Object[]{});
            return value;
        } catch (Exception e) {
            return null;
        }
    }
 
    private static List<Map> getFiledsInfo(Object model) {
        Field[] fields = model.getClass().getDeclaredFields();
        List<Map> list = new ArrayList(fields.length);
        Map infoMap = null;
        for (int i = 0; i < fields.length; i++) {
            infoMap = new HashMap(3);
            infoMap.put("type", fields[i].getType());
            infoMap.put("name", fields[i].getName());
            infoMap.put("value", getFieldValueByName(fields[i].getName(), model));
            list.add(infoMap);
        }
        return list;
    } 
}

使用原生sql查詢:

/**
     * 根據公司名稱查詢崗位
     * @param name 公司名稱
     * @return  List<EmploymentPosition>
     */
    @Query(value = "select id, position, salary, people, experience, address, update_time from employment_position where company_name = ?1 and is_delete is false ORDER BY sort asc", nativeQuery = true)
    List<Object[]> findByCompanyName(String name);

使用類型轉換:

@Override
    public List<EmploymentPositionVO> findByCompanyName(String name) {
        List<Object[]> objects = employmentPositionRepository.findByCompanyName(name);
        return EntityUtils.castEntity(objects, EmploymentPositionVO.class, new EmploymentPositionVO());
    }

VO類如下:

import lombok.Data; 
import java.math.BigInteger;
import java.sql.Timestamp;
 
/**
 * @website https://el-admin.vip
 * @description /
 * @author budezhenjia
 * @date 2021-02-08
 **/
@Data
public class EmploymentPositionVO {
 
    /** ID */
    private BigInteger id;
 
    /** 崗位名稱 */
    private String position;
 
    /** 月薪 */
    private String salary;
 
    /** 人數 */
    private Integer people;
 
    /** 工作經驗 */
    private String experience;
 
    /** 工作地點 */
    private String address;
 
    /** 更新時間 */
    private Timestamp updateTime; 
    public EmploymentPositionVO(BigInteger id, String position, String salary, Integer people, String experience, String address, Timestamp updateTime) {
        this.id = id;
        this.position = position;
        this.salary = salary;
        this.people = people;
        this.experience = experience;
        this.address = address;
        this.updateTime = updateTime;
    } 
    public EmploymentPositionVO() {
    }
}

注意!

查詢sql語句所查詢出來的字段應與VO類中屬性順序一致,類型也需要一致!!

例如ID這個字段MySQL中類型為bigint,VO類中的類型為bigInteger

dto,vo,po,bo等實體轉換工具類

3層開發以及不是多么新穎的開發思想了,但是呢,苦于開發的程序猿們,經常會被各個實例之間的轉換弄得暈頭轉向,尤其是轉換的次數多了,一下就蒙了,不知道轉到哪里去了,博主也有這種困難,于是在網上到處找,找到了一些方法,并結合自身的開發使用,填補一些坑,希望對大家有所幫助!

下面宣布這次的主角:dozer

他是誰,一看英文名就不懂吧,其實他是一個大家都知道的一個角色,spring里面他可是家喻戶曉的一個主角,沒錯就是beanUtils(其實,就是他的替身!)主要作用就是用來復制 JavaBean 屬性的類庫,什么叫復制,沒錯,就一模一樣的再來一份,但是這樣有一點點小小的區別,那就是,在使用的時候,需要指定一個“容器”(瞎說的,就是一個映射接受對象,也可以叫做目標)來存放,不然,復制到哪去,是不是。

這個時候呀,就有一個經紀人的出現,需要通過“經紀人”去代理復制,才能叫這個替身出來呀(專業替身30年,必須要有經紀人)

<dependency>
    <groupId>net.sf.dozer</groupId>
    <artifactId>dozer</artifactId>
    <version>5.5.1</version>
</dependency>

好了,經紀人的名片已經發出,這個時候,找到劇組,咱們看看這個替身能不能勝任,能應用在哪些劇組,哪些場景!

第一種場景,完全一樣:(咦,度一樣了,那肯定好弄,又看不出來區別)

在各個實體是一樣的情況下,是很容易的,直接上不就行啦,也不用做啥處理是不是:

直接是用原始替身(API方法)

 Mapper mapper = new DozerBeanMapper();
DestinationObject destObject =  
    mapper.map(sourceObject, DestinationObject.class);

嘿嘿,換一下衣服,直接OK了(也就是使用mapper轉換復制)

第二種場景,完全不一樣:

求乞,完全不一樣,這咋的弄呀,肯定得換替身,是不是!最起碼找個相似的嘛(不用擔心,咱們有化妝師呀,化妝走起!)

@Data
public class UserVo{
    @Mapping("userName")
    private String name;
    @Mapping("password")
    private String pwd;
}

看一下,是不是這個東西,好眼熟,沒錯,是咱們的vo

@Data
@TableName("user")
public class UserEntity implements Serializable {
    @ApiModelProperty(value = "id")
    @TableId(value = "id", type = IdType.INPUT)
    private String id;
    @ApiModelProperty(value = "用戶名")
    @Mapping("name")
    private String userName;
    @ApiModelProperty(value = "密碼")
    @Mapping("pwd")
    private String password;
    @ApiModelProperty(value = "登錄名")
    private String loginName;
    @ApiModelProperty(value = "創建時間")
    private Date createTime;
    @ApiModelProperty(value = "修改時間")
    private Date updateTime;
    @ApiModelProperty(value = "版本號")
    private Integer version;
    @ApiModelProperty(value = "作廢標記")
    private Integer deleted;
}

這個呢,是咱們的實體對象(也就是數據庫對象了)

看一下,是不是發小完全不一樣呀!

這里呢,@Mappin充當了化妝品的角色,將每一個不同的細節進行遮蓋,使其成為和原來的實例一模一樣(也就是做了映射了)

 @Mapping("userName")
 private String name;

上面就是一個化妝處理,將name映射為userName

每一個地方處理完成后,直接上劇組,看看能不能不被發現

/**
     * 轉換實體為另一個指定的實體
     * 任意一個參數為NULL時 會拋出NPE
     *
     * @param source 源實體 不能為NULL
     * @param clazz 目標實體 不能為NULL
     * @param <T> 泛型
     * @return 轉換后的結果
     */
    @NonNull
    public static <T> T convert(@NonNull Object source, @NonNull Class<T> clazz) {
        return  dozerMapper.map(source, clazz);
    }

實例:

 UserEntity userEntity = userMapper.selectOne(wrapper);
            UserVo convert = null;
            if(userEntity != null){
               convert = Dozer.convert(userEntity, UserVo.class);
            }

沒錯,這樣就完成轉換替身的操作了,結果是可以映射上的,各位可以試試哦!

第三種場景,一堆的不相同的替身(好難呀,一堆的不一樣,不能找幾個差不多的嗎?)

針對于這種一堆的不一樣的替身,dozer也有辦法,通過JAVA8的stream流來進行化妝(化妝師牛,只能這么說)

 /**
     * 轉換List實體為另一個指定的實體
     * source如果為NULL 會使用空集合
     * 在目標實體為NULL時 會拋出NPE
     *
     * @param source 源集合 可以為NULL
     * @param clazz 目標實體 不能為NULL
     * @param <T> 泛型
     * @return 轉換后的結果
     */
    @Nullable
    public static <T> List<T> convert(@Nullable List<?> source, @NonNull Class<T> clazz) {
        return Optional.ofNullable(source)
                .orElse(Collections.emptyList())
                .stream()
                .map(bean -> dozerMapper.map(bean, clazz))
                .collect(Collectors.toList());
    }

看見沒,這樣一弄,就OK了,咦,是不是發現化妝師dozerMapper從哪來的(這么牛的化妝師,召幾個開化妝店去),博主告訴你,這個化妝師呀,并不是越多也好的(大家都知道,一樣的對象,建立太多浪費空間),只需要建立一個全局唯一的就行了,博主帶你們看一下化妝間就明白了(工具類來了)

package cn.yichehuoban.ycbb.platform.util.beanutils;
import org.dozer.Mapper;
import org.springframework.lang.NonNull;
import org.springframework.lang.Nullable;
import org.springframework.stereotype.Component;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
 
@Component
public class Dozer {
    /**
     * dozer轉換的核心mapper對象
     */
    public static final Mapper dozerMapper = new org.dozer.DozerBeanMapper();
    /**
     * 轉換實體為另一個指定的實體
     * 任意一個參數為NULL時 會拋出NPE
     *
     * @param source 源實體 不能為NULL
     * @param clazz 目標實體 不能為NULL
     * @param <T> 泛型
     * @return 轉換后的結果
     */
    @NonNull
    public static <T> T convert(@NonNull Object source, @NonNull Class<T> clazz) {
        return  dozerMapper.map(source, clazz);
    }
    /**
     * 轉換List實體為另一個指定的實體
     * source如果為NULL 會使用空集合
     * 在目標實體為NULL時 會拋出NPE
     *
     * @param source 源集合 可以為NULL
     * @param clazz 目標實體 不能為NULL
     * @param <T> 泛型
     * @return 轉換后的結果
     */
    @Nullable
    public static <T> List<T> convert(@Nullable List<?> source, @NonNull Class<T> clazz) {
        return Optional.ofNullable(source)
                .orElse(Collections.emptyList())
                .stream()
                .map(bean -> dozerMapper.map(bean, clazz))
                .collect(Collectors.toList());
    }
}

在給大家看一下我們的替身

@Data
public class UserVo{
    @Mapping("userName")
    private String name;
    @Mapping("password")
    private String pwd;
    private String loginName;
    private Integer version;
    private Integer deleted;
    private String id;
}

一樣的地方直接就映射上了,不一樣的地方使用 @Mapping注解,填寫上源指定對象的字段名就行。

以上是“如何使用JPA自定義VO類型轉換”這篇文章的所有內容,感謝各位的閱讀!希望分享的內容對大家有幫助,更多相關知識,歡迎關注億速云行業資訊頻道!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

淮阳县| 满城县| 永仁县| 绥芬河市| 武汉市| 莱州市| 抚顺市| 浏阳市| 赞皇县| 八宿县| 枣阳市| 高阳县| 固安县| 宜宾县| 石嘴山市| 耒阳市| 娄底市| 兴义市| 志丹县| 阿瓦提县| 龙岩市| 荆州市| 民权县| 牟定县| 舟山市| 阿荣旗| 寿阳县| 精河县| 佛坪县| 东台市| 巴里| 台南市| 定西市| 安塞县| 安顺市| 曲靖市| 高州市| 抚宁县| 英吉沙县| 林州市| 绥德县|