Java 使用域对象作为带有Spring数据的MongoDB文档ID 背景

Java 使用域对象作为带有Spring数据的MongoDB文档ID 背景,java,mongodb,spring-data,spring-data-mongodb,Java,Mongodb,Spring Data,Spring Data Mongodb,我最近从学习领域驱动设计(DDD)中得到的一个想法是,用具有有意义名称的领域对象包装数据类型(如字符串和原语)是很好的。例如,如果我有一个要存储在MongoDB中的com.example.Account域对象,它可能有一个类型为java.lang.String的id字段。相反,将id字段的类型设置为com.example.AccountId可能会更好,因为这样可以很好地读取代码,并作为代码的一种自我文档提供帮助。它也可以是一种编译时防御措施,防止某人意外地传递另一种id,而这种id恰好也是字符串

我最近从学习领域驱动设计(DDD)中得到的一个想法是,用具有有意义名称的领域对象包装数据类型(如字符串和原语)是很好的。例如,如果我有一个要存储在MongoDB中的
com.example.Account
域对象,它可能有一个类型为
java.lang.String
的id字段。相反,将id字段的类型设置为
com.example.AccountId
可能会更好,因为这样可以很好地读取代码,并作为代码的一种自我文档提供帮助。它也可以是一种编译时防御措施,防止某人意外地传递另一种id,而这种id恰好也是字符串

我在使用SpringDataMongoDB实现这一点时遇到了一些麻烦

例子 使用字符串 我从一个Account对象开始,它只有一个名为“id”的字段,类型为
java.lang.String
。我的Spring数据存储库定义如下:

public interface AccountRepository extends PagingAndSortingRepository<Account, String> {}
public class AccountId implements Serializable {

private final String id;

public AccountId(String id) {
    this.id = id;
}

public String getId() {
    return id;
}

}
然后我将account中id字段的类型更改为
AccountId
,最后将存储库定义更改为:

public interface AccountRepository extends PagingAndSortingRepository<Account, AccountId> {}

我能做些什么(如果有的话)来实现这种行为?

尝试添加setter和默认构造函数。我知道这有点过时了-我从来没有充分解决过这个问题。我尝试了一个默认的构造函数和setter,但没有成功。似乎org.springframework.data.mongodb.core.MongoTemplate#assertUpdateableIdIfNotSet方法检查Id字段的类型是ObjectId、String还是BigInteger。因为我的AccountId不是这些,所以引发异常。在持久化之前,通过调用new ObjectId().toHexString()并将结果传递给构造AccountId,我已经手动设置了AccountId对象。不太理想,但似乎有效。@DavidGoate-你有没有找到更好的解决办法?我面临着完全相同的问题。我可以用你描述的方法来解决它,但我更希望Spring知道如何自动生成ID类的实例。@Nathan-不幸的是,我没有找到更好的方法,但自从这篇文章发表以来,我没有尝试过再次搜索或使用原始方法,所以Spring数据的新版本可能会发挥得更好?或者你在最新版本上有这个问题吗?Spring Mongo 1.9.4,不,它没有更好的表现:(问题是MongoSimpleTypes类及其静态自动生成的_ID_类型。它只包含ObjectId、String和BigInteger,无法注入其他类型或行为。总之,老实说,不是很“spring”:(没关系
org.springframework.dao.InvalidDataAccessApiUsageException: Cannot autogenerate id of type com.example.AccountId for entity of type com.example.Account!
at org.springframework.data.mongodb.core.MongoTemplate.assertUpdateableIdIfNotSet(MongoTemplate.java:1149)
at org.springframework.data.mongodb.core.MongoTemplate.doSave(MongoTemplate.java:878)
at org.springframework.data.mongodb.core.MongoTemplate.save(MongoTemplate.java:833)
at org.springframework.data.mongodb.repository.support.SimpleMongoRepository.save(SimpleMongoRepository.java:72)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)