仅为一个字段编写 Mongo 转换器

2022-09-03 02:40:00

我有一个简单的POJO,里面有一个很长的字段,这实际上是一个时间戳。

此字段必须位于由 ISODate 表示的 mongo 数据库中。

我可以写一个转换器,因为整个Pojo,但由于它只是25个字段中的一个,所以没有多大意义,当一个字段会改变或添加另一个字段时,这是另一个错误的地方。

有没有办法调用默认转换器服务,并在默认转换服务之后更改其他2个,这将对性能产生很大影响。或者是否有要覆盖的默认转换器接口?

这里的最佳实践是什么?

也许有一个注释,我可以应用于此字段?

是的,我也可以写一个LongToDate转换器,但这会影响所有的POJO,而不仅仅是这个。

下面是示例 POJO:

public class Person {
   private long someTimestamp;
//getters and setters
}

如果没有转换器,这将看起来像这样:

{
    "_id" : ObjectId("52ae8eede4b0249cde22059e"),
    "someTimestamp" : NumberLong(1392714950940)
}

结果应该是这样的:

{
    "_id" : ObjectId("52ae8eede4b0249cde22059e"),
    "someTimestamp" : ISODate("2013-12-23T23:00:00.000Z")
}

当这样的时间戳值位于嵌套文档中时,desribed 问题变得更加复杂:

{
    "_id" : ObjectId("52ae8eede4b0249cde22059e"),
    "items" : [
        "someTimestamp" : NumberLong(1392714950940)
    ]
}

POJO:

public class Person {
   private Collection<OtherPojoThatHoldsTimestamps> items;
//getters and setters
}

也许我应该提到我正在使用Spring来实现这一目标。(http://projects.spring.io/spring-data-mongodb/)


答案 1

听起来您需要注释驱动的转换。参考手册中的 6.6.2 节为格式化程序讨论了这一点,甚至还有一个带有时间戳的示例。

一般的想法是,您将使用注释标记需要特殊处理的字段(这是注释的良好用法,毕竟您正在指定元数据)。然后,您将为具有该注释的字段注册转换器。

问题是我刚刚尝试过这个,但无法让它工作,因为元数据丢失了。我已经提交了一张JIRA票证,看看是否有办法解决这个问题。


答案 2

解决方案一是使用spring data mongodb监听器:

package com.rc.user.auth.model.listener;

import com.mongodb.DBObject;
import com.nimbusds.jwt.JWTParser;
import com.rc.user.auth.model.OAuth2AccessTokenEntity;
import org.springframework.data.mongodb.core.mapping.event.AbstractMongoEventListener;
import org.springframework.data.mongodb.core.mapping.event.AfterConvertEvent;
import org.springframework.data.mongodb.core.mapping.event.BeforeSaveEvent;
import org.springframework.stereotype.Component;

import java.text.ParseException;

@Component
public class OAuth2AccessTokenEntityListener extends AbstractMongoEventListener<OAuth2AccessTokenEntity> {

    @Override
    public void onBeforeSave(BeforeSaveEvent<OAuth2AccessTokenEntity> event) {
        OAuth2AccessTokenEntity oat = event.getSource();
        DBObject db = event.getDBObject();

        db.put("tokenValue", oat.getJwt().serialize());
    }

    @Override
    public void onAfterConvert(AfterConvertEvent<OAuth2AccessTokenEntity> event) {

        OAuth2AccessTokenEntity oat = event.getSource();
        DBObject db = event.getDBObject();

       try {
          oat.setJwt(JWTParser.parse(db.get("tokenValue").toString()));
      } catch (ParseException e) {
          e.printStackTrace();
        }
    }
}

解决方案二是使用转换器:

package com.rc.user.auth.model.convert;

import com.nimbusds.jwt.JWT;
import org.springframework.core.convert.converter.Converter;
import org.springframework.data.convert.WritingConverter;


@WritingConverter
public class JWTToStringConverter implements Converter<JWT, String> {

    @Override
    public String convert(JWT jwt) {
        return jwt.serialize();
    }
}