web-dev-qa-db-fra.com

Données de printemps mongodb. Générer une erreur d'identification

J'ai fait une expérience ... une entité commune pour deux référentiels de données Spring: - JPA - MongoDB

tout d’abord, j’utilise les versions suivantes des bibliothèques:

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

J'ai une entité:

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

Le référentiel JPA a l'aspect suivant:

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

Le dépôt MongoDB a l'aspect suivant:

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

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

Donc ... JPA fonctionne :) Rien de spécial:) Mais le test MongoDB n’est pas passé: ( Je reçois une erreur:

 org.springframework.dao.InvalidDataAccessApiUsageException: impossible de générer automatiquement l'id de type Java.lang.Long pour l'entité de type ua.home.springdata.investigation.entity.Account! 
 à 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 (Méthode native) 
 à 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) 
 sur com.Sun.proxy. $ Proxy26.save (Source inconnue) 

Je pense que c'est un cas très commun. Pourquoi les données Spring ne peuvent-elles pas générer d'identifiant d'entité long? Il est tellement bizarre.

12
b3lowster

Les ObjectIds Mongo ne correspondent pas à un type Java Long.

Je vois ceci dans la documentation, sous 7.6.1:

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

Une propriété id ou un champ déclaré en tant que chaîne dans la classe Java sera converti et stocké en tant que ObjectId si possible en utilisant un Spring Convertisseur. Les règles de conversion valides sont déléguées à le pilote MongoDB Java. S'il ne peut pas être converti en un ObjectId, alors la valeur sera stockée sous forme de chaîne dans la base de données.

Une propriété id ou un champ déclaré comme BigInteger dans la classe Java sera être converti et stocké en tant que ObjectId à l’aide de Spring Convertisseur.

Alors changez id en String ou BigInteger et supprimez l'argument de stratégie.

24
Robert Moskal

Utiliser @Id en tant que chaîne fonctionne bien.

Assurez-vous que votre référentiel s'étend avec une chaîne (même type que le @Id):

extends MongoRepository<MyEntity, String>
2
Miguel Reyes

Je pense que le problème est que vous utilisez "Entity" au lieu de "Document". Mongo dao devrait utiliser l'annotation "Document" et le référentiel devrait étendre l'interface "MongoRepository". Ce serait un exemple utilisant ce que vous avez. Tout d’abord, vous voudrez ajouter la dépendance mongo à votre pom (je suppose que vous utilisez le parent print boot, le numéro de version y sera défini)

 <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
 }
1
GSUgambit

J'ai aussi essayé quelque chose comme ça, pour mongo db j'ai dû utiliser la version import org.springframework.data.annotation.Id; de @Id alors que JPA j'ai utilisé import javax.persistence.Id;

1
Romell

Mon projet utilisant Spring Data Rest + mongo

  1. Type de données Je n'utilise ni le type Long ni le BigInteger. C'est un objet personnalisé. Disons CompanyUID.class. Ici, il doit s'agir de MongoRepository<DataLoadMerchant, CompanyUID> comme ce que @Miguel dit Puis j'ai changé mon getter et mon setter. Convertir une chaîne en CompanyUID ou CompanyUID en chaîne

  2. enregistrer le convertisseur à Mongo 

    @Configuration
    public class MongoConfig extends AbstractMongoConfiguration {
    @Override
    public CustomConversions customConversions() {
        converters.add(new CompanyUIDoObjectIdConverter());
        converters.add(new ObjectIdToCompanyUIDConverter());
        return new CustomConversions(converters);
        }
    }
    
  3. nom de colonne. Je regarde le document Mongo. il semble que je ne puisse pas avoir un entityId avec @Id et aussi utiliser entityId comme nom de colonne. Donc, je change setter Ensuite, dans MongoDB, il aura 2 colonnes. Les deux colonnes conservent la même valeur. Et nous utilisons uniquement entityId en tant que clé primaire pour CRUD, même si ce n'est pas la vraie clé primaire.

mon code 

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