关于springboot:记录遇到的mongDb问题-以及restTemplate请求重试

最近应用mongDb的时候,呈现了一些问题。

mongDb 实体id自增

在保留实体的时候报了这个错

Cannot aotogenerate id of type java.lang.Long for entity
不能主动生成id

之后就带着报错去谷歌了一下。 失去了如下后果:

Mongo ObjectIds 与 jave Long 类型不匹配。

先来介绍一下MongoDB 的对象 Id(ObjectId)

ObjectId

ObjectId 是一个12字节 BSON 类型数据,有以下格局:

前4个字节示意工夫戳
接下来的3个字节是机器标识码
紧接的两个字节由过程id组成(PID)
最初三个字节是随机数。

例如 62ee651f cabe7f 59dc f10372

从 MongoDB 3.4 开始(最早公布于 2016 年 12 月),ObjectId 的设计被批改了,两头 5 字节的值由原先的“机器标识码+过程号”改为单纯随机值。

a 4-byte value representing the seconds since the Unix epoch,
a 5-byte random value, and
a 3-byte counter, starting with a random value.


MongoDB中存储的文档必须有一个”_id”键。这个键的值能够是任何类型的,默认是个ObjectId对象。

在一个汇合外面,每个文档都有惟一的”_id”值,来确保汇合外面每个文档都能被惟一标识。

MongoDB采纳ObjectId,而不是其余比拟惯例的做法(比方主动减少的主键)的次要起因,因为在多个 服务器上同步主动减少主键值既费劲还费时。

找出起因

之后就在实体定义中发现, 我定义的id是Long类型。
因为mongoDb主动进行id自增的时候,生成的id并不能转换为Long,所以报了错

@JsonIgnoreProperties(ignoreUnknown = true)
@Document
public class System {

  @Id
  @JsonView
  private Long id;
}

之后改为String 类型之后报错隐没。

在数据库中查看数据,查看到的是ObjectId类型

传到前台,是string类型的数据

总结

在mongoDb中想要让主动设置id的话,须要设置@Id正文,并设置为string类型。

抉择应用 String 属性作为 ID,那么 Mongo 会在保留时主动为其赋值(如果它是空的)。通过抉择 String,您能够取得一个由数据库治理的主动调配的 ID,而不用费神手动设置该属性。

然而目前的我的项目中,id都是从gitlab获取的数据,所以不须要主动设置id,若采纳Long类型,并本人设置id ,失去数据就是这样, 示意 id为22。

MongoDB 长久化实体映射

在网上查了无关实体正文时,遇到了一问题。

spring-data-mongodb次要有以下罕用的注解.

@Id
主键,不可反复,自带索引

@Document
标注在实体类上,相似于hibernate的entity注解,表明由mongo来保护该表

@Document(collection=”mongodb 对应 collection 名”)

@Document
public class System {

  @Id
  @JsonView
  private String id;

跟以前不同的是,不必@Entity注解, 用@Document注解。

@Field : 属性

存储到数据库中的字段名。

加这个注解,就是以注解的值对应mongo的key
不加这个注解,默认以参数对应mongo的key

@Field("user_name")
private String userName;

另外@CompoundIndex 联结索引和@Transient:属性就不具体说了。


关联实体

一个比拟重要的点就是关联实体。

在JPA中, 咱们能够用@ManyToMany,@OneToMany等正文,生成两头表等操作。

然而在mongo中,这些正文貌似并不起作用。

我在尝试增加@ManyToMany后,并没有生成两头表

@DBRef注解

而在mongo实体中,相似@OneToMany等成果的注解是: @DBRef

这个正文示意关联另一个document对象。相似于mysql的表关联。

没有加该正文的状况下,是这样子。作为一般的数据存到labels里。


加了正文的状况,是这样。
这里拿了其余文章的测试后果,我还没测试

能够发现而是只保留了它的id和namespace. 相当于一个援用,或者说是外键。

另外值得注意的是,
这个注解并且不会解决级联保留,你必须独自先保留@DBRef关联的对象。

你须要先respority.save(@DBRef关联的对象),而后再保留原来的对象。

这是其余文章的测试后果:

小结:
看上去mongo解决的形式有点不同。然而目前我的项目中尽管应用了mongo,然而还在应用@Entity以及 @ManyToMany等注解,也没有产生什么报错。

然而从后果来看,@ManyToMany没有生成两头表。对mongo没有用。

restTemplate申请重试

在后盾向gitlab申请数据的时候,无论尝试了几遍,都会报这个谬误。然而他人却能申请。

SSL 异样敞开了。

在之前也报过这个错,网上给出了解决办法个别都是如下。设置一下https协定类型。

System.setProperty("https.protocols", "TLSv1,TLSv1.1,TLSv1.2,SSLv3");

然而尝试了几次都没有成果。


之后查看代码,须要获取35个issue下的评论。 猜想到可能是因为申请次数和数据量相干。

于是就尝试了,当restTemplate申请失败时,减少重试机制

1,装置配置

编辑 pom.xml 文件,增加 相干依赖

<!-- 重试机制 -->
<dependency>
    <groupId>org.springframework.retry</groupId>
    <artifactId>spring-retry</artifactId>
    <version>1.1.2.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjweaver</artifactId>
</dependency>

2.退出 @EnableRetry 注解

@SpringBootApplication(exclude={DataSourceAutoConfiguration.class})
@EnableRetry
@EnableAsync
public class NonlycodeApplication {

3. 应用@Retryable注解

 @Override
 @Retryable(value = {RestClientException.class, EOFException.class}, maxAttempts = 3,
          backoff = @Backoff(delay = 1000L,multiplier = 1))
  public <T> List<T> httGetWithPageRequest(String url, Map<String, String> variables, Integer latestPage, Class<T[]> valueType) throws JsonProcessingException {
   

@Retryable 注解的办法在产生异样时会重试,参数阐明:
value:指定重试异样
maxAttemps:最大重试次数,默认 3
backoff:重试期待策略,默认没有

@Backoff 注解为重试期待策略,参数阐明:
delay:指定重试的延时工夫,默认为 1000L ,1秒
multiplier:指定提早的倍数,默认为 0。比方 delay=5000l,multiplier=2 时,第一次重试为 5 秒后,第二次为 10 秒,第三次为 20 秒。

这样就能在调用这个办法的时候,只有其中某个异样产生时,被注解的办法就会进行重试。

抛出异样

当超过重试次数是异样会被抛出

 //发动申请
    RestTemplate restTemplate = new RestTemplate(new HttpsClientRequestFactory());
    ResponseEntity<String> response = restTemplate.exchange(requestUrl, HttpMethod.GET, new HttpEntity<String>(headers), String.class, variables);

    // 判断申请是否产生异样
    if(!response.getStatusCode().is2xxSuccessful()){
      System.out.println("申请失败...");
      // 抛出异样
      throw new RestClientException(response.getBody());
    }

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理