最近使用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 类型之后报错消失。
总结
在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没有用。