在将请求添加到MongoDB之前如何处理Spring Data中的插入请求?


问题内容

在遵循了https://spring.io/guides/gs/accessing-mongodb-data-
rest/上
的非常有用的教程之后,我正在尝试创建链接缩短程序。我已经编码的URL类(与idlongURLhash属性)和URLRepository类(就目前而言,只用findByHash在演示中所示的方法)。请注意,“散列”指的是由尚待实现的方法生成的随机短字符串,而不是像MD5这样的实际散列函数。只是打电话给一个独立generateHash(String URL)

我可以使用Spring提供的REST接口,以及获取它们,将新条目添加到数据库中。但是我想让应用程序本身生成哈希,并在存储之前进行一些检查和处理-
主要是检查URL是否尚未存储,在这种情况下,它将仅返回现有哈希。

我想,我不得不延长SimpleMongoRepository<S extends T> List<S> save(Iterable<S> entites);方法(如延长了MongoRepository)我下的URLRepository类,但我真的不知道该怎么做。我也看到了该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,因为您基本上需要两种资源:一种用于添加链接或返回现有资源,另一种用于通过哈希来检索原始URI。

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

这很简单,也很容易消化。

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

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);
  }
}

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