DATACOUCH-571 fix delimiters in generated id

Also clean up test domain/Config.java
This commit is contained in:
mikereiche
2020-06-20 10:22:36 -07:00
parent 3d6117d060
commit d89866110a
3 changed files with 199 additions and 111 deletions

View File

@@ -863,6 +863,7 @@ public class MappingCouchbaseConverter extends AbstractCouchbaseConverter implem
sb.append(delimiter);
}
appendKeyParts(sb, idAttributes.values(), delimiter);
isAppending = true;
}
if (generatedValue.strategy() == UNIQUE) {
@@ -870,6 +871,7 @@ public class MappingCouchbaseConverter extends AbstractCouchbaseConverter implem
sb.append(delimiter);
}
sb.append(UUID.randomUUID());
isAppending = true;
}
if (suffixes.size() > 0) {

View File

@@ -34,9 +34,7 @@ import org.springframework.data.convert.WritingConverter;
import org.springframework.data.couchbase.core.convert.CouchbaseCustomConversions;
import org.springframework.data.couchbase.core.convert.CouchbaseJsr310Converters.LocalDateTimeToLongConverter;
import org.springframework.data.couchbase.core.convert.MappingCouchbaseConverter;
import org.springframework.data.couchbase.core.mapping.id.GeneratedValue;
import org.springframework.data.couchbase.core.mapping.id.GenerationStrategy;
import org.springframework.data.couchbase.core.mapping.id.IdPrefix;
import org.springframework.data.couchbase.core.mapping.id.*;
import org.springframework.data.couchbase.domain.Config;
import org.springframework.data.couchbase.domain.User;
import org.springframework.data.mapping.MappingException;
@@ -788,89 +786,140 @@ public class MappingCouchbaseConverterTests {
}
@Test
void idTest00() { // id does not get set
void idNotGenerated() {
class Entity {
public static final String ID = "mockid";
@Id private String id = ID;
}
Entity entity = new Entity();
CouchbaseDocument converted = new CouchbaseDocument();
IdTest00Entity entity = new IdTest00Entity();
converter.write(entity, converted);
Map<String, Object> result = converted.export();
assertThat(converted.getId()).isEqualTo(entity.getId());
}
public static class IdTest00Entity { // id does not get set
public static final String ID = "mockid";
@Id private String id = ID;
String getId() {
return id;
}
assertThat(converted.getId()).isEqualTo(entity.id);
}
@Test
void idTest02() { // id is String
void idIsGeneratedString() {
class Entity {
@GeneratedValue(strategy = GenerationStrategy.UNIQUE) @Id String id;
}
Entity entity = new Entity();
CouchbaseDocument converted = new CouchbaseDocument();
IdTest02Entity entity = new IdTest02Entity();
converter.write(entity, converted);
Map<String, Object> result = converted.export();
assertThat(converted.getId()).isEqualTo(entity.getId());
}
public static class IdTest02Entity { // id is String
@GeneratedValue(strategy = GenerationStrategy.UNIQUE) @Id String id;
String getId() {
return id;
}
assertThat(converted.getId()).isEqualTo(entity.id);
}
@Test
void idTest03() { // id is UUID
CouchbaseDocument converted = new CouchbaseDocument();
IdTest03Entity entity = new IdTest03Entity();
converter.write(entity, converted);
assertThat(converted.getId()).isEqualTo(entity.getId());
}
public static class IdTest03Entity { // id is UUID
@GeneratedValue(strategy = GenerationStrategy.UNIQUE) @Id UUID id;
String getId() {
return id.toString();
void idIsGeneratedUUID() {
class Entity {
@GeneratedValue(strategy = GenerationStrategy.UNIQUE) @Id UUID id;
}
Entity entity = new Entity();
CouchbaseDocument converted = new CouchbaseDocument();
converter.write(entity, converted);
assertThat(converted.getId()).isEqualTo(entity.id.toString());
}
@Test
void idTest05() { // id is Integer
CouchbaseDocument converted = new CouchbaseDocument();
IdTest05Entity entity = new IdTest05Entity();
converter.write(entity, converted);
assertThat(converted.getId()).isEqualTo(entity.getId());
}
public static class IdTest05Entity { // id is Integer
@GeneratedValue() @Id Integer id;
@IdPrefix public String prefix = "123";
String getId() {
return id.toString();
void idIsGeneratedInteger() {
class Entity {
@GeneratedValue() @Id Integer id; // cannot be UNIQUE since a UUID cannot be coerced into an Integer
@IdAttribute public String attribute = "111"; // here's my Integer
}
Entity entity = new Entity();
CouchbaseDocument converted = new CouchbaseDocument();
converter.write(entity, converted);
assertThat(converted.getId()).isEqualTo(entity.id.toString());
}
@Test
void idTest07() { // id is Number
CouchbaseDocument converted = new CouchbaseDocument();
IdTest07Entity entity = new IdTest07Entity();
converter.write(entity, converted);
assertThat(converted.getId()).isEqualTo(entity.getId());
}
public static class IdTest07Entity { // id is Number
@GeneratedValue() @Id public Number id;
@IdPrefix public String prefix = "123";
String getId() {
return id.toString();
void idIsGeneratedNumber() {
class Entity {
@GeneratedValue() @Id public Number id; // cannot be UNIQUE since a UUID cannot be coerced into a Number
@IdAttribute public String attribute = "111"; // here's my number
}
Entity entity = new Entity();
CouchbaseDocument converted = new CouchbaseDocument();
converter.write(entity, converted);
assertThat(converted.getId()).isEqualTo(entity.id.toString());
}
@Test
void idHasPrefix() {
class Entity {
@GeneratedValue(strategy = GenerationStrategy.USE_ATTRIBUTES) @Id public String id;
@IdAttribute public String someId = "abc";
@IdPrefix public String prefix = "111";
}
Entity entity = new Entity();
CouchbaseDocument converted = new CouchbaseDocument();
converter.write(entity, converted);
assertThat(converted.getId()).isEqualTo(entity.id);
assertThat(converted.getId()).isEqualTo(entity.prefix + '.' + entity.someId);
}
@Test
void idHasSuffix() {
class Entity {
@GeneratedValue(strategy = GenerationStrategy.USE_ATTRIBUTES) @Id public String id;
@IdAttribute public String someId = "abc";
@IdSuffix public String suffix = "999";
}
Entity entity = new Entity();
CouchbaseDocument converted = new CouchbaseDocument();
converter.write(entity, converted);
assertThat(converted.getId()).isEqualTo(entity.id);
assertThat(converted.getId()).isEqualTo(entity.someId + '.' + entity.suffix);
}
@Test
void idHasPrefixAndSuffix() {
class Entity {
@GeneratedValue(strategy = GenerationStrategy.USE_ATTRIBUTES) @Id public String id;
@IdAttribute public String someId = "abc";
@IdPrefix public String prefix = "111";
@IdSuffix public String suffix = "999";
}
Entity entity = new Entity();
CouchbaseDocument converted = new CouchbaseDocument();
converter.write(entity, converted);
assertThat(converted.getId()).isEqualTo(entity.id);
assertThat(converted.getId()).isEqualTo(entity.prefix + '.' + entity.someId + '.' + entity.suffix);
}
@Test
void idHasMultiplePrefixesAndSuffixes() {
class Entity {
@GeneratedValue(strategy = GenerationStrategy.USE_ATTRIBUTES) @Id public String id;
@IdAttribute public String someId = "abc";
@IdPrefix(order = 1) public String prefix = "111";
@IdPrefix(order = 3) public String prefix1 = "333";
@IdSuffix(order = 4) public String suffix1 = "444";
@IdSuffix(order = 2) public String suffix = "222";
}
Entity entity = new Entity();
CouchbaseDocument converted = new CouchbaseDocument();
converter.write(entity, converted);
assertThat(converted.getId()).isEqualTo(entity.id);
assertThat(converted.getId()).isEqualTo(
entity.prefix + '.' + entity.prefix1 + '.' + entity.someId + '.' + entity.suffix + '.' + entity.suffix1);
}
@Test
void idHasMultiplePrefixesAndSuffixesSameOrder() { // might want to disallow this
class Entity {
@GeneratedValue(strategy = GenerationStrategy.USE_ATTRIBUTES) @Id public String id;
@IdAttribute public String someId = "abc";
@IdPrefix(order = 1) public String prefix = "111";
@IdPrefix(order = 1) public String prefix1 = "333";
@IdSuffix(order = 1) public String suffix1 = "444";
@IdSuffix(order = 1) public String suffix = "222";
}
Entity entity = new Entity();
CouchbaseDocument converted = new CouchbaseDocument();
converter.write(entity, converted);
assertThat(converted.getId()).isEqualTo(entity.id);
assertThat(converted.getId()).isEqualTo(entity.prefix1 + '.' + entity.someId + '.' + entity.suffix);
}
}

View File

@@ -16,17 +16,31 @@
package org.springframework.data.couchbase.domain;
import org.springframework.data.couchbase.config.BeanNames;
import org.springframework.data.couchbase.core.convert.CouchbaseCustomConversions;
import org.springframework.data.couchbase.core.convert.MappingCouchbaseConverter;
import org.springframework.data.couchbase.core.mapping.CouchbaseMappingContext;
import com.couchbase.client.java.Cluster;
import com.couchbase.client.java.ClusterOptions;
import com.couchbase.client.java.env.ClusterEnvironment;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.auditing.DateTimeProvider;
import org.springframework.data.convert.CustomConversions;
import org.springframework.data.couchbase.CouchbaseClientFactory;
import org.springframework.data.couchbase.SimpleCouchbaseClientFactory;
import org.springframework.data.couchbase.config.AbstractCouchbaseConfiguration;
import org.springframework.data.couchbase.config.BeanNames;
import org.springframework.data.couchbase.core.CouchbaseTemplate;
import org.springframework.data.couchbase.core.ReactiveCouchbaseTemplate;
import org.springframework.data.couchbase.core.convert.CouchbaseCustomConversions;
import org.springframework.data.couchbase.core.convert.MappingCouchbaseConverter;
import org.springframework.data.couchbase.core.mapping.CouchbaseMappingContext;
import org.springframework.data.couchbase.domain.time.AuditingDateTimeProvider;
import org.springframework.data.couchbase.repository.auditing.EnableCouchbaseAuditing;
import org.springframework.data.couchbase.repository.config.EnableCouchbaseRepositories;
import org.springframework.data.couchbase.repository.config.ReactiveRepositoryOperationsMapping;
import org.springframework.data.couchbase.repository.config.RepositoryOperationsMapping;
import org.springframework.data.util.TypeInformation;
import java.lang.reflect.InvocationTargetException;
import java.util.Collections;
/**
* @author Michael Nitschinger
@@ -48,64 +62,42 @@ public class Config extends AbstractCouchbaseConfiguration {
static {
try {
clusterAware = Class.forName("org.springframework.data.couchbase.util.ClusterAwareIntegrationTests");
} catch (ClassNotFoundException cnfe) {
if (clusterAware.getMethod("config").invoke(null) == null)
clusterAware = null;
} catch (ClassNotFoundException | NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
}
String clusterGet( String methodName, String defaultValue){
if (clusterAware != null) {
try {
return (String) clusterAware.getMethod(methodName).invoke(null);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
return defaultValue;
}
@Override
public String getConnectionString() {
if (clusterAware != null) {
try {
if (clusterAware.getMethod("config").invoke(null, (Object[]) null) != null) {
return (String) clusterAware.getMethod("connectionString").invoke(null, (Object[]) null);
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
return connectionString;
return clusterGet( "connectionString", connectionString );
}
@Override
public String getUserName() {
if (clusterAware != null) {
try {
if (clusterAware.getMethod("config").invoke(null, (Object[]) null) != null) {
return (String) clusterAware.getMethod("username").invoke(null, (Object[]) null);
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
return username;
return clusterGet( "username", username );
}
@Override
public String getPassword() {
if (clusterAware != null) {
try {
if (clusterAware.getMethod("config").invoke(null, (Object[]) null) != null) {
return (String) clusterAware.getMethod("password").invoke(null, (Object[]) null);
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
return password;
return clusterGet( "password", password );
}
@Override
public String getBucketName() {
if (clusterAware != null) {
try {
if (clusterAware.getMethod("config").invoke(null, (Object[]) null) != null) {
return (String) clusterAware.getMethod("bucketName").invoke(null, (Object[]) null);
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
return bucketname;
return clusterGet( "bucketName", bucketname );
}
@Bean(name = "auditorAwareRef")
@@ -118,6 +110,51 @@ public class Config extends AbstractCouchbaseConfiguration {
return new AuditingDateTimeProvider();
}
@Override
public void configureReactiveRepositoryOperationsMapping(ReactiveRepositoryOperationsMapping baseMapping) {
try {
ReactiveCouchbaseTemplate personTemplate = myReactiveCouchbaseTemplate(myCouchbaseClientFactory("protected"),new MappingCouchbaseConverter());
baseMapping.mapEntity(Person.class, personTemplate); // Person goes in "protected" bucket
ReactiveCouchbaseTemplate userTemplate = myReactiveCouchbaseTemplate(myCouchbaseClientFactory("mybucket"),new MappingCouchbaseConverter());
baseMapping.mapEntity(User.class, userTemplate); // User goes in "mybucket"
// everything else goes in getBucketName() ( which is travel-sample )
} catch (Exception e) {
throw e;
}
}
@Override
public void configureRepositoryOperationsMapping(RepositoryOperationsMapping baseMapping) {
try {
CouchbaseTemplate personTemplate = myCouchbaseTemplate(myCouchbaseClientFactory("protected"),new MappingCouchbaseConverter());
baseMapping.mapEntity(Person.class, personTemplate); // Person goes in "protected" bucket
CouchbaseTemplate userTemplate = myCouchbaseTemplate(myCouchbaseClientFactory("mybucket"),new MappingCouchbaseConverter());
baseMapping.mapEntity(User.class, userTemplate); // User goes in "mybucket"
// everything else goes in getBucketName() ( which is travel-sample )
} catch (Exception e) {
throw e;
}
}
// do not use reactiveCouchbaseTemplate for the name of this method, otherwise the value of that bean
// will be used instead of the result of this call (the client factory arg is different)
public ReactiveCouchbaseTemplate myReactiveCouchbaseTemplate(CouchbaseClientFactory couchbaseClientFactory,
MappingCouchbaseConverter mappingCouchbaseConverter) {
return new ReactiveCouchbaseTemplate(couchbaseClientFactory, mappingCouchbaseConverter);
}
// do not use couchbaseTemplate for the name of this method, otherwise the value of that been
// will be used instead of the result from this call (the client factory arg is different)
public CouchbaseTemplate myCouchbaseTemplate(CouchbaseClientFactory couchbaseClientFactory,
MappingCouchbaseConverter mappingCouchbaseConverter) {
return new CouchbaseTemplate(couchbaseClientFactory, mappingCouchbaseConverter);
}
// do not use couchbaseClientFactory for the name of this method, otherwise the value of that bean will
// will be used instead of this call being made ( bucketname is an arg here, instead of using bucketName() )
public CouchbaseClientFactory myCouchbaseClientFactory(String bucketName) {
return new SimpleCouchbaseClientFactory(getConnectionString(),authenticator(), bucketName );
}
// convenience constructor for tests
public MappingCouchbaseConverter mappingCouchbaseConverter() {
MappingCouchbaseConverter converter = null;
@@ -136,7 +173,7 @@ public class Config extends AbstractCouchbaseConfiguration {
@Override
@Bean(name = "couchbaseMappingConverter")
public MappingCouchbaseConverter mappingCouchbaseConverter(CouchbaseMappingContext couchbaseMappingContext,
CouchbaseCustomConversions couchbaseCustomConversions) {
CustomConversions couchbaseCustomConversions) {
// MappingCouchbaseConverter relies on a SimpleInformationMapper
// that has an getAliasFor(info) that just returns getType().getName().
// Our CustomMappingCouchbaseConverter uses a TypeBasedCouchbaseTypeMapper that will