目标:查询数据库中的字段,然后转换成 JSON 格式的数据,返回前台。

环境:idea 2016.3.4, jdk 1.8, mysql 5.6, spring-boot 1.5.2 
背景:首先建立 entity 映射数据库(非专业 java 不知道这怎么说)

@Entity
@Table(name = "user")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String userName; // 账号
private String password; // 密码
// getter setter 方法略过
}

  

然后建立与之对应的 model

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

这里我们分情况讨论

首先第一种情况:查询的字段与表中的字段全部对应(就是查表里所有的字段,但是使用 Model 作为接收对象)

这种情况比较简单,调用 Repository 提供的方法,返回一个 entity , 然后将 entity 的属性复制到 model 中。像这样

UserModel user = new UserModel();
User userEntity = new User();
// 一个工具类,具体使用方法请百度
BeanUtils.copyProperties(user, userEntity);

第二种情况:只查询指定的几个字段

现在我有张表,有字段如下:

@Entity
@Table(name = "user_info")
public class UserInfo {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String name = "用户"; // 昵称
private String signature; // 个性签名
private String gender = "未知"; // 性别
private String description; // 个人说明
private String avatar; // 头像
private Long role; // 权限
private Boolean disable; // 是否冻结
private Date createTime; // 创建时间
private Boolean isDelete; // 是否删除
private Long userId; // 用户 Id
// ...
}

但是我只需要查询指定的几个字段,然后转换成 JSON,返回给前台,咋办呢?

第一种方法:使用 model 查询时转化

首先建立一个 model ,写上自己想要查询的字段,然后写上构造函数,这步很重要,因为spring jpa 转化时会调用这个构造方法

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 类中写查询方法

@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();

直接在查询语句中 new model 框架底层会调用它,然后返回这个对象(这里我写了完整的类路径,不写的时候它报错说找不到类型什么的)

然后就可以获得只有指定字段的 model 了。然后就把它转成 JSON 格式就 O 了。

第二种方法:在service 里边转换成 JSON

原理其实和第一种方法差不多,只是处理结果的方式不太一样,只是这种方法我们就不在 hql 中 new Model 了,直接写查询方法

@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(这里得是小写,不知道大写有木有问题,反正没试,编译器提示是要小写的) 
然后返回的结果是这样的

[
{
"0": "admin",
"1": "你猜",
"2": "男",
"3": "一段描述"
}, {
"0": "abc",
"1": "你猜人家",
"2": "女",
"3": "没事先挂了"
}
]

然后在 service 层里直接封装成 JSON 对象,返回

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

还有一种返回结果,这样写:

@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();

返回结果是这样的格式:

[
[
"admin",
"你猜",
"男",
"一段描述"
], [
"abc",
"你猜人家",
"女",
"没事先挂了"
]
]

返回的是数组,也一样可以通过上面的方法转成 json ,这里我的程序中出现了一点点 BUG,就是空值的字段不会在数组中,不知道为什么。

这种方法必须明确的知道查询了哪些字段,灵活性比较差,虽然它解决了手头的问题。还有就是版本的不同,有可能会出现丢失空字段的情况,我个人特别的不喜欢这样的方法,万一我实体几十个字段,写着写着忘了写到哪了,就 over 了

第三种方法:返回一个便于转换成 json 格式的 list

其实和上面很相似,都是 dao 层返回一个 List < Map < String, Object >>,但是上面的结果集返回的 Map 的 key 只是列的下标,这种方式稍微理想一点点,就是 Map 的 key 就是查询的列名。但是这种方式需要实现自定义 Repository( 这里不详细介绍,请自行百度 ),并且只是 jpa 集成 hibenate 的时候可以使用。

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 的接口,这里的做法就是先转成 hibenate 的查询接口对象,然后设置结果转换器
query.unwrap(SQLQuery.class).setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
return query.getResultList();
}

这种方法返回的就是比较标准的 JSON 格式的 java 对象了,只需要用 jackson 或者 Gson 转一下就是标准的 json 了

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

这种方式其实已经比较理想了,因为直接就能返回到前台,但是有时候,结果不是一条 sql 能够解决的,得两条或者以上的 sql 来解决一个复杂的查询需求,这个过程中,结果比较需要转换成 pojo,以便于组装操作。

第四种方案:dao 中直接转成 pojo 返回

这个方案还是依赖于 hibenate,有点操蛋,但是更明确一些。

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)
// 这里是设置字段的数据类型,有几点注意,首先这里的字段名要和目标实体的字段名相同,然后 sql 语句中的名称(别名)得与实体的相同
.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这个常量类,在一些旧版本中,是 Hibenate 类,具体哪个包我不知道,我这个版本中是换成了前面的那个常量类

spring data jpa 查询自定义字段,转换为自定义实体的更多相关文章

  1. spring data jpa查询部分字段、多余附加字段

    spring data jpa查询部分字段 第一种方法:使用 model 查询时转化 首先建立一个 model ,写上自己想要查询的字段,然后写上构造函数,这步很重要,因为spring jpa 转化时 ...

  2. Spring Data JPA 查询结果返回至自定义实体

    本人在实际工作中使用Spring Data Jpa框架时,一般查询结果只返回对应的Entity实体.但有时根据实际业务,需要进行一些较复杂的查询,比较棘手.虽然在框架上我们可以使用@Query注解执行 ...

  3. spring data jpa 查询部分字段列名无效问题

    spring data jpa原生sql查询问题,我只要表其中的几个字段的值,本以为写个原生sql,拿实体类对象去接没问题 结果列名无效,测试了一下,把返回值类型改成List<Object> ...

  4. spring data jpa 查询部分字段

    @Query("select new map(ah as ah,salq as sqlq,yg as yg, bg as bg,ay as ay) FROM Aj where ahdm=?1 ...

  5. 关于Spring Data JPA更新部分字段的问题

    1.问题背景 个人比较喜欢Spring data JPA,这次的问题是在实体类中使用List类型作为字段,JPA也提供了操作的方法,即使用@ElementCollection注解,网上对于JPA的知识 ...

  6. spring boot系列(五)spring boot 配置spring data jpa (查询方法)

    接着上面spring boot系列(四)spring boot 配置spring data jpa 保存修改方法继续做查询的测试: 1 创建UserInfo实体类,代码和https://www.cnb ...

  7. 在Spring Data JPA 中使用Update Query更新实体类

    对于 Spring Data JPA 使用的时间不长,只有两年时间.但是踩过坑的却不少. 使用下列代码 @Modifying @Query("update User u set u.firs ...

  8. Spring Data Jpa 查询返回自定义对象

    转载请注明出处:http://www.wangyongkui.com/java-jpa-query. 今天使用Jpa遇到一个问题,发现查询多个字段时返回对象不能自动转换成自定义对象.代码如下: //U ...

  9. spring data jpa 查询No property ... found for...Did you mean '...'?

    原文地址:https://blog.csdn.net/earthhour/article/details/79271816 实体类字段定义: private String sku_no; dao中接口 ...

随机推荐

  1. 3451: Tyvj1953 Normal 点分治 FFT

    国际惯例的题面:代价理解为重心和每个点这个点对的代价.根据期望的线性性,我们枚举每个点,计算会产生的ij点对的代价即可.那么,i到j的链上,i必须是第一个被选择的点.对于i来说,就是1/dis(i,j ...

  2. Bzoj4598: [Sdoi2016]模式字符串 点分治 哈希

    国际惯例的题面:这种关于树上路径的题,我也没什么好办法,只好点分治.考虑当前分治重心为root,如何统计经过分治重心的路径的答案.我们令prf[i]表示某个点到root的路径(不含root)已经循环匹 ...

  3. Python3练习题系列(01)

    2018-06-13 题目: 根据用户回答做出相应的判断,完成一个“回答-判断”的小游戏 Python3知识点: if, else, elif 实例代码: print("You enter ...

  4. Vs2017 控制台 中文输出是乱码的问题解决

    下午直接用vs写的控制台的东西,然后发现控制台输出的中文是乱码,于是就百度了下.同样的是,百度上很多的答案.我就说下我解决的过程.先上图 第一种方案:有可能是控制台的问题.若是控制台的问题,则与VS无 ...

  5. Detour3.0 win7 64bit下的安装

    最近在做API hook相关的东西,用了inline hook后感觉不错,但是查找资料发现inline hook并不稳定 inline hook 的原理是在系统访问一个函数的时候先替换原函数入口处的内 ...

  6. 好好的P2P,咋说爆就爆?

    P2P 理财就是通过互联网理财,即个人对个人,又称点对点网络借贷 ,是指以公司为中介机构,把借贷双方对接起来实现各自的借贷需求.借款方可以是无抵押贷款或是有抵押贷款,而中介一般是收取双方或单方的手续费 ...

  7. BTrace使用简介

    很多时候在online的应用出现问题时,很多时候我们需要知道更多的程序的运行细节,但又不可能在开发的时候就把程序中所有的运行细节都打印到日志上,通常这个时候能采取的就是修改代码,重新部署,然后再观察, ...

  8. 你真的会用Gson吗?Gson使用指南(4)

    原文出处: 怪盗kidou 注:此系列基于Gson 2.4. 本次文章的主要内容: TypeAdapter JsonSerializer与JsonDeserializer TypeAdapterFac ...

  9. ECharts的geojson地图数据下载(根据城市区划代码的前六位查询)

    链接如下: http://echarts.baidu.com/echarts2/doc/example/geoJson/china-main-city/522200.json 想要对应城市的geojs ...

  10. KVM虚拟化管理 virt manager常用操作

    部分涉及到Linux.Nginx.tomcat.MySQL等的点滴操作记录,时间长了,就忘掉了,偶尔整理一下操作的history,就此简要备份一下: [原][BG]-一次虚拟化环境实践简要记录: ht ...