亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

spring data jpa 查詢(xún)自定義字段,轉(zhuǎn)換為自定義實(shí)體方式

 更新時(shí)間:2021年06月11日 09:01:13   作者:郄灬灬  
這篇文章主要介紹了spring data jpa 查詢(xún)自定義字段,轉(zhuǎn)換為自定義實(shí)體方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教

目標(biāo):查詢(xún)數(shù)據(jù)庫(kù)中的字段,然后轉(zhuǎn)換成 JSON 格式的數(shù)據(jù),返回前臺(tái)。

環(huán)境:idea 2016.3.4, jdk 1.8, mysql 5.6, spring-boot 1.5.2

背景:首先建立 entity 映射數(shù)據(jù)庫(kù)(非專(zhuān)業(yè) java 不知道這怎么說(shuō))

@Entity
@Table(name = "user")
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
    private String userName;    // 賬號(hào)
    private String password;    // 密碼
    // getter setter 方法略過(guò)
}

然后建立與之對(duì)應(yīng)的 model

public class UserModel implements Serializable {
    // 一些屬性
}

這里我們分情況討論

首先第一種情況:

查詢(xún)的字段與表中的字段全部對(duì)應(yīng)(就是查表里所有的字段,但是使用 Model 作為接收對(duì)象)

這種情況比較簡(jiǎn)單,調(diào)用 Repository 提供的方法,返回一個(gè) entity , 然后將 entity 的屬性復(fù)制到 model 中。像這樣

UserModel user = new UserModel();
User userEntity = new User();
// 一個(gè)工具類(lèi),具體使用方法請(qǐng)百度
BeanUtils.copyProperties(user, userEntity);

第二種情況:只查詢(xún)指定的幾個(gè)字段

現(xiàn)在我有張表,有字段如下:

@Entity
@Table(name = "user_info")
public class UserInfo {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
    private String name = "用戶";     // 昵稱(chēng)
    private String signature;         // 個(gè)性簽名
    private String gender = "未知";   // 性別
    private String description;       // 個(gè)人說(shuō)明
    private String avatar;            // 頭像
    private Long role;                // 權(quán)限
    private Boolean disable;          // 是否凍結(jié)
    private Date createTime;          // 創(chuàng)建時(shí)間
    private Boolean isDelete;         // 是否刪除
    private Long userId;              // 用戶 Id
    // ...
}

但是我只需要查詢(xún)指定的幾個(gè)字段,然后轉(zhuǎn)換成 JSON,返回給前臺(tái),咋辦呢?

第一種方法:使用 model 查詢(xún)時(shí)轉(zhuǎn)化

首先建立一個(gè) model ,寫(xiě)上自己想要查詢(xún)的字段,然后寫(xiě)上構(gòu)造函數(shù),這步很重要,因?yàn)閟pring jpa 轉(zhuǎn)化時(shí)會(huì)調(diào)用這個(gè)構(gòu)造方法

public class MyModel implements Serializable {
    private String userName;
    private String name;
    private String gender;
    private String description;
    public MyModel() {};
    public MyModel(String userName, String name, String gender, String description) {
        this.userName = userName;
        this.name = name;
        this.gender = gender;
        this.description = description;
    }
}

然后在 dao 類(lèi)中寫(xiě)查詢(xún)方法

@Query(value = "select new pers.zhuch.model.MyModel(u.userName, ui.name, ui.gender, ui.description) from UserInfo ui, User u where u.id = ui.userId")
public List<MyModel> getAllRecord();

直接在查詢(xún)語(yǔ)句中 new model 框架底層會(huì)調(diào)用它,然后返回這個(gè)對(duì)象(這里我寫(xiě)了完整的類(lèi)路徑,不寫(xiě)的時(shí)候它報(bào)錯(cuò)說(shuō)找不到類(lèi)型什么的)

然后就可以獲得只有指定字段的 model 了。然后就把它轉(zhuǎn)成 JSON 格式就 O 了。

第二種方法:在service 里邊轉(zhuǎn)換成 JSON

原理其實(shí)和第一種方法差不多,只是處理結(jié)果的方式不太一樣,只是這種方法我們就不在 hql 中 new Model 了,直接寫(xiě)查詢(xún)方法

@Query(value = "select new map(u.userName, ui.name, ui.gender, ui.description) from UserInfo ui, User u where u.id = ui.userId")
public List<Map<String, Object>> getCustomField();

直接new map(這里得是小寫(xiě),不知道大寫(xiě)有木有問(wèn)題,反正沒(méi)試,編譯器提示是要小寫(xiě)的)

然后返回的結(jié)果是這樣的

[
    {
        "0": "admin",
        "1": "你猜",
        "2": "男",
        "3": "一段描述"
    }, {
        "0": "abc",
        "1": "你猜人家",
        "2": "女",
        "3": "沒(méi)事先掛了"
    }
]

然后在 service 層里直接封裝成 JSON 對(duì)象,返回

List<JsonObject> list = new ArrayList();
for(Map map : result) {
    JsonObject j = new JsonObject();
    j.addProperty(attrName, val);
    ...
    list.add(j);
}
gson.toJson(list);

還有一種返回結(jié)果,這樣寫(xiě):

@Query(value = "select u.userName, ui.name, ui.gender, ui.description from UserInfo ui, User u where u.id = ui.userId")
public List<Object> getCustomField();

返回結(jié)果是這樣的格式:

[
    [
        "admin",
        "你猜",
        "男",
        "一段描述"
    ], [
        "abc",
        "你猜人家",
        "女",
        "沒(méi)事先掛了"
    ]
]

返回的是數(shù)組,也一樣可以通過(guò)上面的方法轉(zhuǎn)成 json ,這里我的程序中出現(xiàn)了一點(diǎn)點(diǎn) BUG,就是空值的字段不會(huì)在數(shù)組中,不知道為什么。

這種方法必須明確的知道查詢(xún)了哪些字段,靈活性比較差,雖然它解決了手頭的問(wèn)題。還有就是版本的不同,有可能會(huì)出現(xiàn)丟失空字段的情況,我個(gè)人特別的不喜歡這樣的方法,萬(wàn)一我實(shí)體幾十個(gè)字段,寫(xiě)著寫(xiě)著忘了寫(xiě)到哪了,就 over 了

第三種方法:返回一個(gè)便于轉(zhuǎn)換成 json 格式的 list

其實(shí)和上面很相似,都是 dao 層返回一個(gè) List < Map < String, Object >>,但是上面的結(jié)果集返回的 Map 的 key 只是列的下標(biāo),這種方式稍微理想一點(diǎn)點(diǎn),就是 Map 的 key 就是查詢(xún)的列名。

但是這種方式需要實(shí)現(xiàn)自定義 Repository( 這里不詳細(xì)介紹,請(qǐng)自行百度 ),并且只是 jpa 集成 hibenate 的時(shí)候可以使用。

public List getCustomEntity() {
    String sql = "select t.id, t.name, t.gender, t.is_delete, t.create_time, t.description from t_entity t";
    Query query = em.createNativeQuery(sql);
    // Query 接口是 spring-data-jpa 的接口,而 SQLQuery 接口是 hibenate 的接口,這里的做法就是先轉(zhuǎn)成 hibenate 的查詢(xún)接口對(duì)象,然后設(shè)置結(jié)果轉(zhuǎn)換器
    query.unwrap(SQLQuery.class).setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
    return query.getResultList();
}

這種方法返回的就是比較標(biāo)準(zhǔn)的 JSON 格式的 java 對(duì)象了,只需要用 jackson 或者 Gson 轉(zhuǎn)一下就是標(biāo)準(zhǔn)的 json 了

 [
    {
        attr: val,
        ...
    },
    {
        attr: val,
        ...
    },
]

這種方式其實(shí)已經(jīng)比較理想了,因?yàn)橹苯泳湍芊祷氐角芭_(tái),但是有時(shí)候,結(jié)果不是一條 sql 能夠解決的,得兩條或者以上的 sql 來(lái)解決一個(gè)復(fù)雜的查詢(xún)需求,這個(gè)過(guò)程中,結(jié)果比較需要轉(zhuǎn)換成 pojo,以便于組裝操作。

第四種方案:dao 中直接轉(zhuǎn)成 pojo 返回

這個(gè)方案還是依賴(lài)于 hibenate,有點(diǎn)操蛋,但是更明確一些。

public List getCustomEntity() {
    String sql = "select t.id, t.name, t.gender, t.is_delete as isEnable, t.create_time as createTime, t.description from t_entity t";
    Query query = em.createNativeQuery(sql);
    query.unwrap(SQLQuery.class)
    // 這里是設(shè)置字段的數(shù)據(jù)類(lèi)型,有幾點(diǎn)注意,首先這里的字段名要和目標(biāo)實(shí)體的字段名相同,然后 sql 語(yǔ)句中的名稱(chēng)(別名)得與實(shí)體的相同
            .addScalar("id", StandardBasicTypes.LONG)
            .addScalar("name", StandardBasicTypes.STRING)
            .addScalar("gender", StandardBasicTypes.STRING)
            .addScalar("isEnable", StandardBasicTypes.BOOLEAN)
            .addScalar("createTime", StandardBasicTypes.STRING)
            .addScalar("description", StandardBasicTypes.STRING)
            .setResultTransformer(Transformers.aliasToBean(EntityModel.class));
    return query.getResultList();
}

這次返回的就是 List 了。這里要注意的是 StandardBasicTypes這個(gè)常量類(lèi),在一些舊版本中,是 Hibenate 類(lèi),具體哪個(gè)包我不知道,我這個(gè)版本中是換成了前面的那個(gè)常量類(lèi)

繼承jpa Repository 寫(xiě)自定義方法查詢(xún)

今天在寫(xiě)jpa查詢(xún)的時(shí)候,遇到了添加自定義方法,項(xiàng)目啟動(dòng)報(bào)錯(cuò)原因,現(xiàn)總結(jié)如下:

首先定義實(shí)體類(lèi)

@Entity
@Table(name = "user")
Class User{
     @Id
    @GeneratedValue 
      int id;
      @Column
      String age;
      @Column
      String school;
      @Column
      String userName;
  set,get方法 (省略)
}
public interface UserRepository extends JpaRepository<User, Long> {
      List<User> findByUsernameLike(String username);
     List<User> aaa();
}

啟動(dòng)項(xiàng)目時(shí),項(xiàng)目報(bào)錯(cuò)提示信息為:

org.springframework.data.mapping.PropertyReferenceException: No property aaa found for type com.fpi.safety.common.entity.po.User

再將List<User> aaa();方法去掉后,項(xiàng)目又可以正常啟動(dòng)運(yùn)行

是什么原因呢?

經(jīng)查找,原來(lái)是繼承jpa,必須滿足一些規(guī)則,規(guī)則如下

Spring Data JPA框架在進(jìn)行方法名解析時(shí),會(huì)先把方法名多余的前綴截取掉,比如find,findBy,read,readBy,get,getBy,然后對(duì)剩下的部分進(jìn)行解析。

假如創(chuàng)建如下的查詢(xún):findByUserName(),框架在解析該方法時(shí),首先剔除findBy,然后對(duì)剩下的屬性進(jìn)行解析,假設(shè)查詢(xún)實(shí)體為User

1:先判斷userName(根據(jù)POJO規(guī)范,首字母變?yōu)樾?xiě))是否為查詢(xún)實(shí)體的一個(gè)屬性,如果是,則表示根據(jù)該屬性進(jìn)行查詢(xún);如果沒(méi)有該屬性,繼續(xù)第二步;

2:從右往左截取第一個(gè)大寫(xiě)字母開(kāi)頭的字符串此處是Name),然后檢查剩下的字符串是否為查詢(xún)實(shí)體的一個(gè)屬性,如果是,則表示根據(jù)該屬性進(jìn)行查詢(xún);如果沒(méi)有該屬性,則重復(fù)第二步,繼續(xù)從右往左截取;最后假設(shè)用戶為查詢(xún)實(shí)體的一個(gè)屬性;

3:接著處理剩下部分(UserName),先判斷用戶所對(duì)應(yīng)的類(lèi)型是否有userName屬性,如果有,則表示該方法最終是根據(jù)“User.userName”的取值進(jìn)行查詢(xún);否則繼續(xù)按照步驟2的規(guī)則從右往左截取,最終表示根據(jù)“User.userName”的值進(jìn)行查詢(xún)。

4:可能會(huì)存在一種特殊情況,比如User包含一個(gè)的屬性,也有一個(gè)userNameChange屬性,此時(shí)會(huì)存在混合。可以明確在屬性之間加上“_”以顯式表達(dá)意思,比如“findByUser_NameChange )“或者”findByUserName_Change()“

從上面,我們可以得知,jap在解析是,aaa在user類(lèi)中是沒(méi)有屬性的,所以報(bào)錯(cuò)No property aaa found.

如果我們想要使用jap框架,又不想再多增加一個(gè)自定義類(lèi),則必須符合其命名規(guī)則

如果,你記不住jpa的規(guī)則也沒(méi)關(guān)系,你可以自己再多寫(xiě)一個(gè)類(lèi)來(lái)實(shí)現(xiàn)自定義查詢(xún)方法

如下:

1. 自定義一個(gè)接口,該接口用來(lái)聲明自己額外定義的查詢(xún)。

public interface UseerRepositoryTwo {
    public List<User> searchUser(String name, int id);
}

2. 創(chuàng)建一個(gè)接口,該接口 extends JpaRepository 或者 CurdRepository, 以及上面自己定義的接口 UseerRepositoryTwo

public interface UserRepositoryTwoService extends CrudRepository<LogDTO, Integer>, CustomizedLogRepository {
}

3. 實(shí)現(xiàn)UserRepositoryTwoService

注意此處的類(lèi)名,必須以 2 中創(chuàng)建的接口的名字UserRepositoryTwoService,后面加上 Impl 來(lái)聲明,而不是寫(xiě)成 UseerRepositoryTwoImpl

public class UserRepositoryTwoServiceImpl implements UserRepositoryTwoService {
    @Autowired
    @PersistenceContext
    private EntityManager entityManager;
    @Override
    public List<User> searchLogs(int Id, String name) {
        ......
    }
}

自己在寫(xiě)自定義實(shí)現(xiàn)即可

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

相關(guān)文章

  • RabbitMQ?Stream插件使用案例代碼

    RabbitMQ?Stream插件使用案例代碼

    這篇文章主要介紹了RabbitMQ?Stream插件使用案例代碼,2.4版為RabbitMQ流插件引入了對(duì)RabbitMQStream插件Java客戶端的初始支持,需要的朋友可以參考下
    2024-04-04
  • Java數(shù)據(jù)結(jié)構(gòu)和算法之鏈表詳解

    Java數(shù)據(jù)結(jié)構(gòu)和算法之鏈表詳解

    鏈表是一種物理存儲(chǔ)單元上非連續(xù)、非順序的存儲(chǔ)結(jié)構(gòu),java代碼實(shí)現(xiàn)單鏈表,插入,刪除和遍歷等功能,這篇文章主要給大家介紹了關(guān)于Java數(shù)據(jù)結(jié)構(gòu)和算法之鏈表的相關(guān)資料,需要的朋友可以參考下
    2024-01-01
  • Java Web請(qǐng)求與響應(yīng)實(shí)例詳解

    Java Web請(qǐng)求與響應(yīng)實(shí)例詳解

    這篇文章主要介紹了Java Web請(qǐng)求與響應(yīng)實(shí)例詳解的相關(guān)資料,需要的朋友可以參考下
    2016-05-05
  • MyBatis處理枚舉類(lèi)型的方法詳解

    MyBatis處理枚舉類(lèi)型的方法詳解

    MyBatis 處理枚舉類(lèi)型的機(jī)制相對(duì)直接,它提供了一種靈活的方式來(lái)處理Java枚舉(enum)類(lèi)型和數(shù)據(jù)庫(kù)之間的映射,本文給大家介紹了MyBatis處理枚舉類(lèi)型的兩種方法,需要的朋友可以參考下
    2024-07-07
  • Java中的匿名對(duì)象定義與用法實(shí)例分析

    Java中的匿名對(duì)象定義與用法實(shí)例分析

    這篇文章主要介紹了Java中的匿名對(duì)象定義與用法,結(jié)合實(shí)例形式分析了java匿名對(duì)象的概念、原理、定義與相關(guān)使用注意事項(xiàng),需要的朋友可以參考下
    2019-08-08
  • 使用Gson將字符串轉(zhuǎn)換成JsonObject和JsonArray

    使用Gson將字符串轉(zhuǎn)換成JsonObject和JsonArray

    這篇文章主要介紹了使用Gson將字符串轉(zhuǎn)換成JsonObject和JsonArray,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-02-02
  • springboot項(xiàng)目不加端口號(hào)也可以訪問(wèn)項(xiàng)目的方法步驟分析

    springboot項(xiàng)目不加端口號(hào)也可以訪問(wèn)項(xiàng)目的方法步驟分析

    這篇文章主要介紹了springboot項(xiàng)目不加端口號(hào)也可以訪問(wèn)項(xiàng)目的方法,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-04-04
  • springboot+Quartz實(shí)現(xiàn)任務(wù)調(diào)度的示例代碼

    springboot+Quartz實(shí)現(xiàn)任務(wù)調(diào)度的示例代碼

    本篇文章主要介紹了springboot + Quartz 實(shí)現(xiàn)任務(wù)調(diào)度的示例代碼,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2018-02-02
  • Springboot整合微信支付(訂單過(guò)期取消及商戶主動(dòng)查單)

    Springboot整合微信支付(訂單過(guò)期取消及商戶主動(dòng)查單)

    本文主要介紹了Springboot整合微信支付(訂單過(guò)期取消及商戶主動(dòng)查單),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2022-07-07
  • Java_異常類(lèi)(錯(cuò)誤和異常,兩者的區(qū)別介紹)

    Java_異常類(lèi)(錯(cuò)誤和異常,兩者的區(qū)別介紹)

    下面小編就為大家?guī)?lái)一篇Java_異常類(lèi)(錯(cuò)誤和異常,兩者的區(qū)別介紹) 。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2016-09-09

最新評(píng)論