为了账号安全,请及时绑定邮箱和手机立即绑定

Restful服务 MyBatis 多表查询大量字段时结果集映射解决方案?

Restful服务 MyBatis 多表查询大量字段时结果集映射解决方案?

慕田峪4524236 2019-03-21 18:19:47
MyBatis 无论是 resultType 还是 resultMap 都需要一个实体例如我们这样一个SQL<mapper namespace="com.savorgames.dao.MemberMapper">   <select id="test" resultType="com.savorgames.domain.Member">       SELECT username,password FROM "user";  </select></mapper>Member实体public class Member {        private int uid;    private String username;    private String password;    private String email;    private String nickname;        public int getUid() {        return uid;    }    public void setUid(int uid) {        this.uid = uid;    }    public String getUsername() {        return username;    }    public void setUsername(String username) {        this.username = username;    }    public String getPassword() {        return password;    }    public void setPassword(String password) {        this.password = password;    }    public String getEmail() {        return email;    }    public void setEmail(String email) {        this.email = email;    }    public String getNickname() {        return nickname;    }    public void setNickname(String nickname) {        this.nickname = nickname;    }}结果集映射MapperList<Member>现在问题来了,做restful服务器时候,将实体转换成 json 会出现大量空值 并暴露数据库表字段,传输的json也相对变大了例如:[{"uid":0,"username":"阿斯达","password":null,"email":null,"nickname":null},{"uid":0,"username":"阿萨法","password":null,"email":null,"nickname":null},{"uid":0,"username":"阿斯达","password":null,"email":null,"nickname":null},{"uid":0,"username":"啊实打实的","password":null,"email":null,"nickname":null},{"uid":0,"username":"阿斯达啊","password":null,"email":null,"nickname":null},{"uid":0,"username":"是打算打","password":null,"email":null,"nickname":null},{"uid":0,"username":"阿斯达","password":"12312312","email":null,"nickname":null}]总不能每一个sql语句都写一个实体类吧,如何灵活的处理 MyBatis 结果集,只返回查询字段?
查看完整描述

5 回答

?
杨魅力

TA贡献1811条经验 获得超6个赞

正确的做法是不改变实体类(DO),

  1. 新建数据传输类(DTO),例如MemberDTO,

  2. 写一个方法吧DO转化成DTO,一个DTO包含的数据可能来自好几个DO,就像你现在需要传输Member的数据,如果需要其他表的一些属性怎么办。

DO是保持和数据库一致的,DTO是保持跟外界交互一致的,这样在数据或者业务发生变动的时候,可以灵活的调整。
千万不要把DO直接拿来做数据传输,这样不利于扩展


查看完整回答
反对 回复 2019-04-19
?
慕哥9229398

TA贡献1877条经验 获得超6个赞

这个跟Mybatis没有半毛钱关系吧,应该是json序列化的配置问题。

我假设你用的是SpringMVC+Jackson,Jackson的序列化配置如下:


<mvc:annotation-driven>

    <mvc:message-converters register-defaults="true">

        <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">

            <property name="objectMapper">

                <bean class="org.springframework.http.converter.json.Jackson2ObjectMapperFactoryBean">

            <property name="serializationInclusion" value="NON_NULL"/><!-- 重点:只输出非NULL字段 -->

        </bean>

    </mvc:message-converters>

</mvc:annotation-driven>

可以看一下@JsonInclude的几个枚举变量对应的含义,个人认为最理想的应该是用NON_EMPTY,这个会把空对象、空数组也不输出(例如:{}, [])。但要注意的是:0也会被认为是EMPTY从而不输出(意味着所有没赋值或为0的int类型或Integer对象都不会被输出)。


查看完整回答
反对 回复 2019-04-19
?
小怪兽爱吃肉

TA贡献1852条经验 获得超1个赞

将对象转换为JSON时(序列化过程),如果对象的某个属性值为null,则该属性不参与序列化,生成的JSON结果也不会包含该属性。代码如下:


public String toNotifyBody(NotifyBean bean) {

        HashMap<String, Object> map = new HashMap<String, Object>();

        map.put("orderId", bean.orderId);

        map.put("title", bean.title);

        map.put("subject", bean.subject);

        map.put("operateType", bean.operateType);

        map.put("handlePerson", bean.handlePerson);

        map.put("extractPerson", bean.extractPerson);

        map.put("sla", bean.sla);

        return JSON.toJSONString(map);

    }

将上述参数,放在map中,然后调用json的方法JSON.toJSONString()的时候,对于null值,是不传输的。我们看一下JSON.toJSONString()方法的实现。


public static final String toJSONString(Object object) {

        return toJSONString(object, new SerializerFeature[0]);

    }

    public static final String toJSONString(Object object, SerializerFeature... features) {

        SerializeWriter out = new SerializeWriter();


        try {

            JSONSerializer serializer = new JSONSerializer(out);

            for (com.alibaba.fastjson.serializer.SerializerFeature feature : features) {

                serializer.config(feature, true);

            }


            serializer.write(object);


            return out.toString();

        } finally {

            out.close();

        }

    }


查看完整回答
反对 回复 2019-04-19
?
慕码人8056858

TA贡献1803条经验 获得超6个赞

如果没有实体类,暴露数据表字段是必然的。

不知道你使用的什么方法生成 JSON,不过理论上来说,应该会有一个忽略空值的参数,找找看,如果实在找不到,可以用正则表达式把空属性去掉。


查看完整回答
反对 回复 2019-04-19
?
FFIVE

TA贡献1797条经验 获得超6个赞

构建对应的实体类是必须的,只显示需要展示的内容,并对数据的格式进行转换(比如date转string等)


查看完整回答
反对 回复 2019-04-19
  • 5 回答
  • 0 关注
  • 2321 浏览

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号