Spring数据mongodb。生成id的错误

时间:2014-10-26 15:04:24

标签: java mongodb spring-data spring-data-mongodb

我做了一个实验......两个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 Repository具有以下外观:

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

MongoDB存储库具有以下外观:

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

public interface Repository extends CrudRepository<Account, Long> {
}

所以... JPA工作:)没什么特别的:) 但MongoDB测试没有通过:( 我收到了错误:

org.springframework.dao.InvalidDataAccessApiUsageException: Cannot autogenerate id of type java.lang.Long for entity of type ua.home.springdata.investigation.entity.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:73)
    at org.springframework.data.mongodb.repository.support.SimpleMongoRepository.save(SimpleMongoRepository.java:88)
    at org.springframework.data.mongodb.repository.support.SimpleMongoRepository.save(SimpleMongoRepository.java:45)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.executeMethodOn(RepositoryFactorySupport.java:442)
    at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.doInvoke(RepositoryFactorySupport.java:427)
    at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.invoke(RepositoryFactorySupport.java:381)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207)
    at com.sun.proxy.$Proxy26.save(Unknown Source)

我认为这是一个非常常见的案例。为什么Spring数据不能生成实体ID为Long?这太奇怪了。

6 个答案:

答案 0 :(得分:26)

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并删除策略参数。

答案 1 :(得分:4)

使用extends MongoRepository<MyEntity, String> 作为字符串可以正常工作。

确保您的存储库使用String扩展(与@Id类型相同):

onOptionsItemSelected()

答案 2 :(得分:3)

默认情况下,mongo集合中的id是字符串。要在收藏夹中保留较长的对象ID,您可以选择一个单独的字段,如下所示:

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

  @Field("my_object_id")
  private Long myObjectId;

答案 3 :(得分:2)

我认为问题在于您使用的是Entity而不是Document。 Mongo dao应使用Document注释,存储库应扩展MongoRepository接口。这将是一个使用你拥有的东西的例子。首先,您要将mongo依赖项添加到您的pom中(我假设您使用的是spring boot parent,因此将在那里定义版本号)

<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 :(得分:1)

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

答案 5 :(得分:0)

我的项目使用Spring Data Rest + mongo

  1. 数据类型 我没有使用任何类型的LongBigInteger。它是自定义对象。让我们说CompanyUID.class。正如@Miguel所说,它必须是MongoRepository<DataLoadMerchant, CompanyUID> 然后我改变了我的吸气剂和二传手。将String转换为CompanyUIDCompanyUID转换为String

  2. 在Mongo注册转换器

  3. @Configuration
    public class MongoConfig extends AbstractMongoConfiguration {
        @Override
        public CustomConversions customConversions() {
            converters.add(new CompanyUIDoObjectIdConverter());
            converters.add(new ObjectIdToCompanyUIDConverter());
            return new CustomConversions(converters);
        }
    }
    
    1. 列名。 我看一下mongo文件。似乎我不能使用@Id的entityId,也使用entityId作为我的列名。所以我改变了setter 然后在MongoDB中它将有2列 一个是_id,另一个是entityId。两列保持相同的值。我们只使用entityId作为CRUD的主键,即使它不是真正的主键
    2. 我的代码

      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;
          }
      }