春季数据MongoDB。生成id的错误

Posted

技术标签:

【中文标题】春季数据MongoDB。生成id的错误【英文标题】:Spring data mongodb. Generating id's error 【发布时间】:2014-12-21 20:31:34 【问题描述】:

我做了一个实验......两个 Spring 数据存储库的一个通用实体: - JPA - MongoDB

首先我使用以下库版本:

spring-data-jpa:1.7.0.RELEASE spring-data-mongodb:1.6.0.RELEASE

我有一个实体:

@Entity
@Table(name = "ACCOUNTS")
public class Account 

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "ACCOUNT_ID")
    private Long id;

    @Column(name = "ACCOUNT_NUMBER")
    private String number;

    public Account() 
    

    public Account(String number) 
        this.number = number;
    

    public Long getId() 
        return id;
    

    public void setId(Long id) 
        this.id = id;
    

    public String getNumber() 
        return number;
    

    public void setNumber(String number) 
        this.number = number;
    

JPA 存储库具有以下外观:

public interface Repository extends CrudRepository<Account, Long> 
    public Account findByNumber(String number);

MongoDB 存储库具有以下外观:

包ua.home.springdata.investigation.repository.mongo;

public interface Repository extends CrudRepository<Account, Long> 

所以... JPA 有效 :) 没什么特别的 :) 但是 MongoDB 测试没有通过:( 我收到一个错误:

org.springframework.dao.InvalidDataAccessApiUsageException:无法为 ua.home.springdata.investigation.entity.Account 类型的实体自动生成 java.lang.Long 类型的 id! 在 org.springframework.data.mongodb.core.MongoTemplate.assertUpdateableIdIfNotSet(MongoTemplate.java:1149) 在 org.springframework.data.mongodb.core.MongoTemplate.doSave(MongoTemplate.java:878) 在 org.springframework.data.mongodb.core.MongoTemplate.save(MongoTemplate.java:833) 在 org.springframework.data.mongodb.repository.support.SimpleMongoRepository.save(SimpleMongoRepository.java:73) 在 org.springframework.data.mongodb.repository.support.SimpleMongoRepository.save(SimpleMongoRepository.java:88) 在 org.springframework.data.mongodb.repository.support.SimpleMongoRepository.save(SimpleMongoRepository.java:45) 在 sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 在 sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) 在 sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 在 org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.executeMethodOn(RepositoryFactorySupport.java:442) 在 org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.doInvoke(RepositoryFactorySupport.java:427) 在 org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.invoke(RepositoryFactorySupport.java:381) 在 org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) 在 org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207) 在 com.sun.proxy.$Proxy26.save(未知来源)

我认为这是一个非常普遍的情况。为什么 Spring 数据不能像 Long 一样生成实体 ID?太奇怪了。

【问题讨论】:

当我添加注释 @GeneratedValue 时,我的 IDE 会在那里抛出错误。我在我的“pom.xml”文件中使用了 jpa 依赖项,但即使这样也不起作用,因为我得到的是它搜索 mysql DB 并且我使用的是 NoSQL (mongoDB)。所以如果你能帮我做点什么,请做。提前致谢。 @Neil Stockton 当我添加注释 @GeneratedValue 时,我的 IDE 会在那里抛出错误。我在我的“pom.xml”文件中使用了 jpa 依赖项,但即使这样也不起作用,因为我得到的是它搜索 MySQL DB 并且我使用的是 NoSQL (mongoDB)。所以如果你能帮我做点什么,请做。提前谢谢.. 【参考方案1】:

Mongo ObjectIds 不映射到 java Long 类型。

我在 7.6.1 下的文档中看到了这一点:

http://docs.spring.io/spring-data/mongodb/docs/current/reference/html/#mongo-template.id-handling

在 Java 类中声明为 String 的 id 属性或字段将是 如果可能,使用 Spring 转换为 ObjectId 并存储为 转换器。有效的转换规则委托给 MongoDB Java 驱动程序。如果无法转换为 ObjectId, 然后该值将作为字符串存储在数据库中。

在 Java 类中声明为 BigInteger 的 id 属性或字段将 使用 Spring 转换为 ObjectId 并存储为 转换器

将 id 更改为 String 或 BigInteger 并删除 strategy 参数。

【讨论】:

那么我将失去与 Spring JPA 实现的兼容性:( @Robert Moskal 当我添加注释 @GeneratedValue 时,我的 IDE 会在那里抛出错误。我在我的“pom.xml”文件中使用了 jpa 依赖项,但即使这样也不起作用,因为我得到的是它搜索 MySQL DB 并且我使用的是 NoSQL (mongoDB)。所以如果你能帮我做点什么,请做。提前致谢。 添加一个新问题并标记我【参考方案2】:

默认情况下,mongo 集合中的 id 是字符串。要在collection中维护一个long id的objects,可以选择一个单独的字段,如下:

  @Id
  @Field("_id")
  @JsonIgnore
  private String id;

  @Field("my_object_id")
  private Long myObjectId;

【讨论】:

【参考方案3】:

我认为问题在于您使用的是Entity 而不是Document。 Mongo dao 应该使用 Document 注释,并且存储库应该扩展 MongoRepository 接口。这将是一个使用您所拥有的示例。首先,您需要将 mongo 依赖项添加到您的 pom 中(我假设您使用的是 spring boot 父级,因此将在此处定义版本号)

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
import org.springframework.data.annotation.Id; 
import org.springframework.data.mongodb.core.mapping.Document;

@Document(collection = "ACCOUNTS")
public class Account 

    @Id
    private String id;

    ....rest of properties


import org.springframework.data.mongodb.repository.MongoRepository;
public interface AccountRepository extends MongoRepository<Account, String>  
    //any extra queries needed

【讨论】:

【参考方案4】:

我的项目使用 Spring Data Rest + mongo

    数据类型 我没有使用LongBigInteger 中的任何一种。它是自定义对象。假设CompanyUID.class。正如@Miguel 所说,这里必须是MongoRepository&lt;DataLoadMerchant, CompanyUID&gt; 然后我改变了我的getter和setter。将String 转换为CompanyUID 或将CompanyUID 转换为String

    Mongo 中的寄存器转换器

@Configuration
public class MongoConfig extends AbstractMongoConfiguration 
    @Override
    public CustomConversions customConversions() 
        converters.add(new CompanyUIDoObjectIdConverter());
        converters.add(new ObjectIdToCompanyUIDConverter());
        return new CustomConversions(converters);
    

    列名。 我看 mongo 文件。看来我不能有一个带有@Id 的 entityId,也不能使用 entityId 作为我的列名。所以我改变了二传手 然后在 MongoDB 中它将有 2 列 一个是_id,另一个是entityId。两列保持相同的值。而且我们只使用 entityId 作为 CRUD 的主键,即使它不是真正的主键

我的代码

public class ClassA implements Serializable 
    @Id
    public CompanyUID id;
    public CompanyUID entityId;

    public String getId() 
        return this.id.toString();
    

    public void setId(String id) 
        if (id != null && this.entityId != null) 
            if (!id.equals(this.entityId)) 
                throw new Exception();
            
        
        this.id = new CompanyUID(id);
        this.entityId = this.id;
    

    public String getEntityId() 
        return entityId.toString();
    

    public void setEntityId(String entityId) 
        if (this.id != null && entityId != null) 
            if (!id.equals(entityId)) 
                throw new Exception();
            
        

        this.entityId = new CompanyUID(entityId);
        this.id = this.entityId;
    

【讨论】:

【参考方案5】:

我也尝试过类似的方法,对于 mongo db,我必须使用 @Idimport org.springframework.data.annotation.Id; 版本,而 JPA 我使用 import javax.persistence.Id;

【讨论】:

【参考方案6】:

使用@Id 作为字符串可以正常工作。

确保您的存储库以字符串(与@Id 相同的类型)扩展:

extends MongoRepository<MyEntity, String>

【讨论】:

以上是关于春季数据MongoDB。生成id的错误的主要内容,如果未能解决你的问题,请参考以下文章

linux安装mongodb数据库./mongod -f mongodb.conf失败或者error

mongodb 启动错误

mongodb启动服务时候报错。错误1067,进程意外终止。

MongoDB exception: connect failed

mongo和mongod的区别

mongodb 数据自动备份