Données de printemps mongodb. Générer l'erreur de id
j'ai fait une expérience... une entité commune pour deux dépôts de données de source: - JPA - MongoDB!--5-->
tout d'abord je' l'aide de bibliothèques suivantes versions:
spring-data-jpa: 1.7.0.PUBLIER printemps de données 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 le regard suivant:
public interface Repository extends CrudRepository<Account, Long> {
public Account findByNumber(String number);
}
le dépôt MongoDB a le regard suivant:
paquet ua.maison.springdata.enquête.référentiel.mongo;
public interface Repository extends CrudRepository<Account, Long> {
}
... JPA fonctionne :) rien de spécial :) Mais le test de MongoDB n'est pas réussi. :( J'obtiens une erreur:
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)
je pense que c'est un cas très commun. Pourquoi Spring data n'est-il pas capable de générer des ID d'entity aussi longtemps? C'est tellement bizarre.
5 réponses
les objets Mongotidiens ne correspondent pas à un type java Long.
je vois cela dans la documentation, dans le cadre 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é comme chaîne de caractères dans la classe Java sera converti et stocké en ObjectId si possible à L'aide D'un ressort Convertisseur. Les règles de conversion valables sont déléguées à le pilote Java de MongoDB. Si elle ne peut pas être convertie en un objectif, alors la valeur sera stockée comme une chaîne dans la base de données.
une propriété ou un champ id déclaré comme BigInteger dans la classe Java être converti et stocké en ObjectId à L'aide D'un ressort Convertisseur.
alors changez id en chaîne ou BigInteger et supprimez l'argument de stratégie.
en utilisant @Id
comme une corde fonctionne bien.
assurez-vous que votre dépôt s'étend avec une chaîne (même type que @Id):
extends MongoRepository<MyEntity, String>
j'ai essayé quelque chose comme ça aussi, pour mongo db, j'ai dû utiliser le import org.springframework.data.annotation.Id;
version de @Id
alors que JPA j'ai utilisé import javax.persistence.Id;
je pense que le problème est que vous utilisez "Entity" au lieu de "Document". Mongo dao devrait utiliser l'annotation " Document "et le dépôt devrait étendre l'interface" MongoRepository". Ce serait un exemple utilisant ce que vous avez. Tout d'abord, vous voulez ajouter la dépendance mongo à votre pom (je suppose que vous utilisez spring boot parent, donc 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
}
mon projet utilisant les données de printemps Rest + mongo
type de données Je n'utilise ni L'un ni L'autre type de Long ou BigInteger. C'est l'Objet personnalisé. Disons CompanyUID.classe. Ici, il doit être
MongoRepository<DataLoadMerchant, CompanyUID>
comme quoi @Miguel dit Puis j'ai changé mes getter et setter. Convertissez String en CompanyUID ou CompanyUID en Stringregistre convertisseur en Mongo
@Configuration public class MongoConfig extends AbstractMongoConfiguration { @Override public CustomConversions customConversions() { converters.add(new CompanyUIDoObjectIdConverter()); converters.add(new ObjectIdToCompanyUIDConverter()); return new CustomConversions(converters); } }
nom de la colonne. Je regarde le document de mongo. il semble que je ne peux pas avoir un entityId avec @Id et aussi utiliser entityId comme nom de colonne. Alors je change de setter Puis en MongoDB il y aura 2 colonnes On est _id et l'autre est entityId. Les deux colonnes conservent la même valeur. Et nous n'utilisons entityId que comme 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;
}
}