MongoDB 使用 java mongo 驱动程序自动递增 id 字段?
MongoDB Auto-Incrementing id field with java mongo driver?
一整天我都在努力寻找问题的答案:
“如何在实体中添加自动递增的“id”字段class?”.
我正在使用 Morphia(Mongo 数据库的类型安全 java 库)。经过几个小时的源代码挖掘和谷歌搜索后,我找到了一个 LongIdEntity class in org.mongodb.morphia.utils 包。基于此 class 我实施了以下解决方案。见下文:
城市class:
@Entity
public class City {
@Id
private Long id;
}
酒店class:
@Entity
public class Hotel {
@Id
private Long id;
}
CityLongIdEntity class:
public class CityLongIdEntity extends LongIdEntity {
public CityLongIdEntity(Datastore ds) {
super(ds);
}
}
HotelLongIdEntity class:
public class HotelLongIdEntity extends LongIdEntity {
public HotelLongIdEntity(Datastore ds) {
super(ds);
}
}
DAO 实现:
CityDAO class:
public class CityDAO extends BasicDAO<City, Long> {
public CityDAO(Datastore ds) {
super(ds);
}
@Override
public Key<City> save(City c) {
if (c.getId() == null) {
CityLongIdEntity ent = new CityLongIdEntity(getDs());
getDs().save(ent);
c.setId(ent.getMyLongId());
}
return getDs().save(c);
}
}
HotelDAO class:
public class HotelDAO extends BasicDAO<Hotel, Long> {
public HotelDAO(Datastore ds) {
super(ds);
}
@Override
public Key<Hotel> save(Hotel h) {
if (h.getId() == null) {
HotelLongIdEntity ent = new HotelLongIdEntity(getDs());
getDs().save(ent);
h.setId(ent.getMyLongId());
}
return getDs().save(h);
}
}
或者您可以在 Github
上查看所有这些代码
UML 图也可用:
所有这些代码都按预期工作,我很高兴,但我有几个问题:
- 如您所见,对于每个实体,我需要创建额外的实体,例如:对于实体
City
,我创建了 CityLongIdEntity
(该实体是自动递增功能的关键部分)。在这种情况下,如果我的应用程序将有 20 个实体(City
、Address
、Hotel
、User
、Room
、Order
等)我需要创建 40 classes!恐怕,但我认为这将是“代码味道”。 我说得对吗?
- 此外,
Entity
不知道 EntityNameLongIdEntity
,EntityNameLongIdEntity
也不知道 Entity
是谁。并且只有特定的 EntityDAO
class 结合使用那些 classes。可以吗? 或者又是code smell?
- 每个
EntityDAO
class 覆盖扩展 BasicDAO
class 并覆盖方法 save()
。不同 DAO
classes 的重写方法 save()
之间的差异很小。我害怕。那就是代码重复和代码异味。 我说得对吗?
请发表您的意见。
我们需要某些实体的数字 ID,但我们的实现方式略有不同:
- 我们对所有实体使用常规的 ObjectId。如果需要,我们会添加一个数字 ID。
- 有一个专用的 AutoIncrementEntity,它为不同的键保存一个计数器——这就是你的 class 名字。
- 我们不使用 DAO,而是使用通用的保存方法,我们在其中检查我们是否有一个 class 的实例和一个数字 ID。如果尚未设置该 ID,我们将获取一个并更新 AutoIncrementEntity。 relevant method 目前未使用 - 如果完全不清楚请告诉我,我会完成该代码。
我的实现中还有两件事可能有点令人困惑:
- 您始终可以提供起始编号,因此我们的数字 ID 可以是 1000、1001、1002...而不是 1、2、3...
- AutoIncrementEntity 中的键不需要是 class,它也可以是子集。例如,您要对公司内的员工进行编号,那么公司 A 的员工的键为
employee-A
,公司 B 的键为 company-B
,...
一整天我都在努力寻找问题的答案:
“如何在实体中添加自动递增的“id”字段class?”.
我正在使用 Morphia(Mongo 数据库的类型安全 java 库)。经过几个小时的源代码挖掘和谷歌搜索后,我找到了一个 LongIdEntity class in org.mongodb.morphia.utils 包。基于此 class 我实施了以下解决方案。见下文:
城市class:
@Entity
public class City {
@Id
private Long id;
}
酒店class:
@Entity
public class Hotel {
@Id
private Long id;
}
CityLongIdEntity class:
public class CityLongIdEntity extends LongIdEntity {
public CityLongIdEntity(Datastore ds) {
super(ds);
}
}
HotelLongIdEntity class:
public class HotelLongIdEntity extends LongIdEntity {
public HotelLongIdEntity(Datastore ds) {
super(ds);
}
}
DAO 实现:
CityDAO class:
public class CityDAO extends BasicDAO<City, Long> {
public CityDAO(Datastore ds) {
super(ds);
}
@Override
public Key<City> save(City c) {
if (c.getId() == null) {
CityLongIdEntity ent = new CityLongIdEntity(getDs());
getDs().save(ent);
c.setId(ent.getMyLongId());
}
return getDs().save(c);
}
}
HotelDAO class:
public class HotelDAO extends BasicDAO<Hotel, Long> {
public HotelDAO(Datastore ds) {
super(ds);
}
@Override
public Key<Hotel> save(Hotel h) {
if (h.getId() == null) {
HotelLongIdEntity ent = new HotelLongIdEntity(getDs());
getDs().save(ent);
h.setId(ent.getMyLongId());
}
return getDs().save(h);
}
}
或者您可以在 Github
上查看所有这些代码UML 图也可用:
所有这些代码都按预期工作,我很高兴,但我有几个问题:
- 如您所见,对于每个实体,我需要创建额外的实体,例如:对于实体
City
,我创建了CityLongIdEntity
(该实体是自动递增功能的关键部分)。在这种情况下,如果我的应用程序将有 20 个实体(City
、Address
、Hotel
、User
、Room
、Order
等)我需要创建 40 classes!恐怕,但我认为这将是“代码味道”。 我说得对吗? - 此外,
Entity
不知道EntityNameLongIdEntity
,EntityNameLongIdEntity
也不知道Entity
是谁。并且只有特定的EntityDAO
class 结合使用那些 classes。可以吗? 或者又是code smell? - 每个
EntityDAO
class 覆盖扩展BasicDAO
class 并覆盖方法save()
。不同DAO
classes 的重写方法save()
之间的差异很小。我害怕。那就是代码重复和代码异味。 我说得对吗?
请发表您的意见。
我们需要某些实体的数字 ID,但我们的实现方式略有不同:
- 我们对所有实体使用常规的 ObjectId。如果需要,我们会添加一个数字 ID。
- 有一个专用的 AutoIncrementEntity,它为不同的键保存一个计数器——这就是你的 class 名字。
- 我们不使用 DAO,而是使用通用的保存方法,我们在其中检查我们是否有一个 class 的实例和一个数字 ID。如果尚未设置该 ID,我们将获取一个并更新 AutoIncrementEntity。 relevant method 目前未使用 - 如果完全不清楚请告诉我,我会完成该代码。
我的实现中还有两件事可能有点令人困惑:
- 您始终可以提供起始编号,因此我们的数字 ID 可以是 1000、1001、1002...而不是 1、2、3...
- AutoIncrementEntity 中的键不需要是 class,它也可以是子集。例如,您要对公司内的员工进行编号,那么公司 A 的员工的键为
employee-A
,公司 B 的键为company-B
,...