-
Notifications
You must be signed in to change notification settings - Fork 186
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
DATACOUCH-275 Key auto generation using Attributes, UUID
Original pull request: #142.
- Loading branch information
1 parent
766e4ee
commit 069ceea
Showing
14 changed files
with
797 additions
and
25 deletions.
There are no files selected for viewing
7 changes: 7 additions & 0 deletions
7
...integration/java/org/springframework/data/couchbase/IntegrationTestCustomKeySettings.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
package org.springframework.data.couchbase; | ||
|
||
import org.springframework.context.annotation.Configuration; | ||
|
||
@Configuration | ||
public class IntegrationTestCustomKeySettings extends IntegrationTestApplicationConfig { | ||
} |
147 changes: 147 additions & 0 deletions
147
...tion/java/org/springframework/data/couchbase/core/CouchbaseTemplateIdGenerationTests.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,147 @@ | ||
package org.springframework.data.couchbase.core; | ||
|
||
import static org.junit.Assert.*; | ||
import static org.springframework.data.couchbase.core.mapping.id.GenerationStrategy.*; | ||
|
||
import com.couchbase.client.java.Bucket; | ||
import com.couchbase.client.java.error.DocumentDoesNotExistException; | ||
import org.junit.Rule; | ||
import org.junit.Test; | ||
import org.junit.rules.TestName; | ||
import org.junit.runner.RunWith; | ||
import org.springframework.beans.factory.annotation.Autowired; | ||
import org.springframework.data.annotation.Id; | ||
import org.springframework.data.couchbase.IntegrationTestApplicationConfig; | ||
import org.springframework.data.couchbase.core.mapping.Document; | ||
import org.springframework.data.couchbase.core.mapping.id.GeneratedValue; | ||
import org.springframework.data.couchbase.core.mapping.id.IdAttribute; | ||
import org.springframework.data.couchbase.core.mapping.id.IdPrefix; | ||
import org.springframework.data.couchbase.core.mapping.id.IdSuffix; | ||
import org.springframework.test.context.ContextConfiguration; | ||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; | ||
|
||
/** | ||
* @author Subhashni Balakrishnan | ||
*/ | ||
@RunWith(SpringJUnit4ClassRunner.class) | ||
@ContextConfiguration(classes = IntegrationTestApplicationConfig.class) | ||
public class CouchbaseTemplateIdGenerationTests { | ||
|
||
@Rule | ||
public TestName testName = new TestName(); | ||
|
||
@Autowired | ||
private Bucket client; | ||
|
||
@Autowired | ||
private CouchbaseTemplate template; | ||
|
||
|
||
private void removeIfExist(String key) { | ||
try { | ||
client.remove(key); | ||
} | ||
catch (DocumentDoesNotExistException e) { | ||
//ignore | ||
} | ||
} | ||
|
||
@Test | ||
public void shouldGenerateIdUsingAtrributes() throws Exception { | ||
SimpleClassWithGeneratedIdValueUsingAttributes simpleClass = new SimpleClassWithGeneratedIdValueUsingAttributes(); | ||
String generatedId = template.getGeneratedId(simpleClass); | ||
|
||
removeIfExist(generatedId); | ||
assertEquals("Id generation should be correct", generatedId, | ||
"prefix1::prefix2::0::1::2.0::3.0::4::Simple::Nested{value:simple}::suffix1::suffix2"); | ||
template.insert(simpleClass); | ||
assertEquals("Exists after insert", true, template.exists(generatedId)); | ||
simpleClass.value = "modified"; | ||
template.save(simpleClass); | ||
SimpleClassWithGeneratedIdValueUsingAttributes modifiedClass = template.findById(generatedId, | ||
SimpleClassWithGeneratedIdValueUsingAttributes.class); | ||
assertEquals("Get after save id should be correct", generatedId, modifiedClass.id); | ||
template.update(simpleClass); | ||
SimpleClassWithGeneratedIdValueUsingAttributes updatedClass = template.findById(generatedId, | ||
SimpleClassWithGeneratedIdValueUsingAttributes.class); | ||
assertEquals("Get after update id should be correct", generatedId, updatedClass.id); | ||
template.remove(generatedId); | ||
assertEquals("Exists after remove", false, template.exists(generatedId)); | ||
} | ||
|
||
@Test | ||
public void shouldGenerateIdUsingUUID() throws Exception { | ||
SimpleClassWithGeneratedIdValueUsingUUID simpleClass = new SimpleClassWithGeneratedIdValueUsingUUID(); | ||
String generatedId = template.getGeneratedId(simpleClass); | ||
simpleClass.id = generatedId; | ||
template.insert(simpleClass); | ||
assertEquals("Should not regenerate id", generatedId, simpleClass.id); | ||
template.remove(generatedId); | ||
assertEquals("Exists after remove", false, template.exists(generatedId)); | ||
} | ||
|
||
|
||
@Document | ||
static class SimpleClassWithGeneratedIdValueUsingAttributes { | ||
|
||
@Id @GeneratedValue(strategy = USE_ATTRIBUTES, delimiter = "::") | ||
public String id; | ||
|
||
@IdAttribute(order = 6) | ||
public Nested nested = new Nested("simple"); | ||
|
||
@IdAttribute(order = 5) | ||
public String type = "Simple"; | ||
|
||
@IdAttribute(order = 4) | ||
public int intNum = 4; | ||
|
||
@IdAttribute(order = 2) | ||
public float floatNum = 2F; | ||
|
||
@IdAttribute(order = 3) | ||
public double doubleNum = 3; | ||
|
||
@IdAttribute | ||
public long longNum = 0L; | ||
|
||
@IdAttribute(order = 1) | ||
public short shortNum = 1; | ||
|
||
@IdPrefix(order = 1) | ||
public String prefix2 = "prefix2"; | ||
|
||
@IdPrefix | ||
public String prefix1 = "prefix1"; | ||
|
||
@IdSuffix(order = 1) | ||
public String suffix2 = "suffix2"; | ||
|
||
@IdSuffix | ||
public String suffix1 = "suffix1"; | ||
|
||
public String value = "new"; | ||
|
||
} | ||
|
||
static class Nested { | ||
private String value; | ||
|
||
public Nested(String value) { | ||
this.value = value; | ||
} | ||
|
||
@Override | ||
public String toString() { | ||
return "Nested{value:" + value + "}"; | ||
} | ||
} | ||
|
||
@Document | ||
static class SimpleClassWithGeneratedIdValueUsingUUID { | ||
@Id @GeneratedValue(strategy = UNIQUE) | ||
public String id; | ||
|
||
public String value = "new"; | ||
} | ||
} |
63 changes: 63 additions & 0 deletions
63
...ation/java/org/springframework/data/couchbase/core/CouchbaseTemplateKeySettingsTests.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
package org.springframework.data.couchbase.core; | ||
|
||
import static org.junit.Assert.*; | ||
|
||
import com.couchbase.client.java.Bucket; | ||
import com.couchbase.client.java.error.DocumentDoesNotExistException; | ||
import com.couchbase.client.java.repository.annotation.Id; | ||
import org.junit.Before; | ||
import org.junit.Rule; | ||
import org.junit.Test; | ||
import org.junit.rules.TestName; | ||
import org.junit.runner.RunWith; | ||
import org.springframework.beans.factory.annotation.Autowired; | ||
import org.springframework.data.couchbase.IntegrationTestCustomKeySettings; | ||
import org.springframework.data.couchbase.core.mapping.Document; | ||
import org.springframework.data.couchbase.core.mapping.KeySettings; | ||
import org.springframework.test.context.ContextConfiguration; | ||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; | ||
|
||
/** | ||
* @author Subhashni Balakrishnan | ||
*/ | ||
|
||
@RunWith(SpringJUnit4ClassRunner.class) | ||
@ContextConfiguration(classes = IntegrationTestCustomKeySettings.class) | ||
public class CouchbaseTemplateKeySettingsTests { | ||
|
||
@Rule | ||
public TestName testName = new TestName(); | ||
|
||
@Autowired | ||
private CouchbaseTemplate template; | ||
|
||
@Before | ||
public void setup() { | ||
if (template.keySettings() == null) { | ||
template.keySettings(KeySettings.build().prefix("MyAppPrefix").suffix("MyAppSuffix").delimiter("::")); | ||
} | ||
} | ||
|
||
@Test | ||
public void shouldAddCustomKeySettings() throws Exception { | ||
SimpleClass simpleClass = new SimpleClass(); | ||
String generatedId = template.getGeneratedId(simpleClass); | ||
assertEquals("Id generated should include custom key settings", "MyAppPrefix::myId::MyAppSuffix", generatedId); | ||
} | ||
|
||
@Test | ||
public void shouldNotAllowKeySettingsToBeChanged() { | ||
try { | ||
template.keySettings(KeySettings.build().prefix("MyAppPrefix").suffix("MyAppSuffix").delimiter("::")); | ||
fail("excepted unsupportedOperationException"); | ||
} catch(Exception ex) { | ||
|
||
} | ||
} | ||
|
||
@Document | ||
static class SimpleClass { | ||
@Id | ||
public String id = "myId"; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
[[couchbase.autokeygeneration]] | ||
= Auto generating keys | ||
|
||
This chapter describes how couchbase document keys can be auto-generated using builtin mechanisms. | ||
There are two types of auto-generation strategies supported. | ||
|
||
- <<couchbase.autokeygeneration.usingattributes>> | ||
- <<couchbase.autokeygeneration.unique>> | ||
|
||
NOTE: The maximum key length supported by couchbase is 250 bytes. | ||
|
||
[[couchbase.autokeygeneration.configuration]] | ||
== Configuration | ||
|
||
Keys to be auto-generated should be annotated with `@GeneratedValue`. The default strategy is `USE_ATTRIBUTES`. Prefix | ||
and suffix for the key can be provided as part of the entity itself, these values are not persisted, they are only | ||
used for key generation. The prefixes and suffixes are ordered using the `order` value. The default order is `0`, multiple | ||
prefixes without order will overwrite the previous. If a value for id is already available, auto-generation will be skipped. | ||
The delimiter for concatenation can be provided using `delimiter`, the default delimiter is `.`. | ||
|
||
.Annotation for GeneratedValue | ||
==== | ||
[source,java] | ||
---- | ||
@Document | ||
public class User { | ||
@Id @GeneratedValue(strategy = USE_ATTRIBUTES, delimiter = ".") | ||
private String id; | ||
@IdPrefix(order=0) | ||
private String userPrefix; | ||
@IdSuffix(order=0) | ||
private String userSuffix; | ||
... | ||
} | ||
---- | ||
==== | ||
|
||
Common prefix and suffix for all entities keys can be added to `CouchbaseTemplate` directly. Once added to the `CouchbaseTemplate`, | ||
they become immutable. These settings are always applied irrespective of the `GeneratedValue` annotation. | ||
|
||
.Common key settings in CouchbaseTemplate | ||
==== | ||
[source,java] | ||
---- | ||
@Autowired | ||
CouchbaseTemplate couchbaseTemplate; | ||
... | ||
couchbaseTemplate.keySettings(KeySettings.build().prefix("ApplicationA").suffix("Server1").delimiter("::")); | ||
---- | ||
==== | ||
|
||
Key will be auto-generated only for operations with direct entity input like insert, update, save, delete using entity. | ||
For other operations requiring just the key, it can be generated using `CouchbaseTemplate`. | ||
|
||
.Standalone key generation in CouchbaseTemplate | ||
==== | ||
[source,java] | ||
---- | ||
@Autowired | ||
CouchbaseTemplate couchbaseTemplate; | ||
... | ||
String id = couchbaseTemplate.getGeneratedId(entity); | ||
... | ||
repo.exists(id); | ||
---- | ||
==== | ||
|
||
[[couchbase.autokeygeneration.usingattributes]] | ||
== Key generation using attributes | ||
|
||
It is a common practice to generate keys using a combination of the document attributes. Key generation using attributes | ||
concatenates all the attribute values annotated with `IdAttribute`, based on the ordering provided similar to prefixes and suffixes. | ||
|
||
.Annotation for IdAttribute | ||
==== | ||
[source,java] | ||
---- | ||
@Document | ||
public class User { | ||
@Id @GeneratedValue(strategy = USE_ATTRIBUTES) | ||
private String id; | ||
@IdAttribute | ||
private String userid; | ||
... | ||
} | ||
---- | ||
==== | ||
|
||
[[couchbase.autokeygeneration.unique]] | ||
== Key generation using uuid | ||
|
||
This auto-generation uses UUID random generator to generate document keys consuming 16 bytes of key space. This mechanism | ||
is only recommended for test scaffolding. | ||
|
||
.Annotation for Unique key generation | ||
==== | ||
[source,java] | ||
---- | ||
@Document | ||
public class User { | ||
@Id @GeneratedValue(strategy = UNIQUE) | ||
private String id; | ||
... | ||
} | ||
---- | ||
==== |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.