如何在将 Spring 数据添加到 MongoDB 之前处理插入请求?

How to process insert requests in Spring Data before adding them to MongoDB?

在学习了 https://spring.io/guides/gs/accessing-mongodb-data-rest/ 上非常有用的教程之后,我正在尝试创建一个 link 缩短器应用程序。我编写了一个 URL class(具有 idlongURLhash 属性)和 URLRepository class(对于现在,仅使用演示中所示的 findByHash 方法)。请注意,"hash" 指的是由尚未实现的方法生成的随机短字符串,而不是像 MD5 这样的实际哈希函数。只需调用一个独立的 generateHash(String URL) 例如

我可以使用 Spring 提供的 REST 接口向数据库中添加新条目,也可以获取它们。但是我想让应用程序自己生成哈希并在存储它之前进行一些检查和处理 - 主要检查 URL 是否尚未存储,在这种情况下它只会 return 现有的散列。

我想我必须在我的 URLRepository class 下扩展 SimpleMongoRepository<S extends T> List<S> save(Iterable<S> entites); 方法(由 MongoRepository 扩展),但我不确定该怎么做。我也看到了 insert 方法,但我不知道我应该使用哪个

URL.java

public class URL {

    @Id private String id;

    private String longURL;
    private String hash;

    public String getLongURL() {
        return longURL;
    }

    public void setLongURL(String longURL) {
        this.longURL = longURL;
    }

    public String getHash() {
        return hash;
    }

    public void setHash(String Hash) {
        this.hash = Hash;
    }

}

URLRepository.java

import org.springframework.data.mongodb.repository.MongoRepository;
import org.springframework.data.repository.query.Param;
import org.springframework.data.rest.core.annotation.RepositoryRestResource;
import org.springframework.util.Assert;

@RepositoryRestResource(collectionResourceRel = "urls", path = "urls")
public interface URLRepository extends MongoRepository<URL, String> {

    List<URL> findByHash(@Param("hash") String hash);

}

感觉你最好写一个自定义控制器而不是在这里使用 Spring Data REST,因为你基本上需要两种资源:一种是添加 link 或 return一个现有的和第二个通过其哈希检索原始 URI。

在第一种方法中,您只需调用存储库方法 findByLongURL(…) 并使用获得的 URL 实例(如果您有结果)或采取第二步实际创建哈希并保存URL 实例思想库。第二个资源基本上只是调用你已经存在的方法。

这很简单易懂。

如果您需要将前一种方法的实现作为原子操作,则需要手动实现存储库查询方法(有关一般说明,请阅读 reference documentation 中的相关部分):

class UrlRepositoryImpl implements UrlRepositoryCustom {

  private final MongoOperations operations;

  public UrlRepositoryImpl(MongoOperations operations) {
    this.operations = operations;
  }

  @Override
  public URL findOrInsert(String source) {

    // What to find?
    Query query = Query.query(Criteria.where("longURL").is(source);

    // What to write if nothing can be found
    Update update = new Update()
      .setOnInsert("longURL", source)
      .setOnInsert("hash", calculatedHash);

    FindAndModifyOptions options = new FindAndModifyOptions.options()
      .returnNew(true) // returns the document insert (if so)
      .upsert(true); // insert document if it doesn't exist

    return operations.findAndModify(query, update, options, URL.class);
  }
}

如您所见,这涉及处理一些较低级别的细节(尽管使用静态导入可以减少冗长),但基本上为您提供了一个原子操作。