DATACOUCH-154 - Guess design doc as uncapitalized class name.
In the SimpleCouchbaseRepository the guessed design document was lowercase of the entity class, whereas in ViewBasedCouchbaseQuery it is uncapitalized (only first letter is lowercase). This has been made consistent, using the uncapitalize method. The doc now reflects that and explicitly have examples with camel case classes (UserInfo instead of User).
This commit is contained in:
34
README.md
34
README.md
@@ -75,27 +75,27 @@ To simplify the creation of data repositories Spring Data Couchbase provides a g
|
||||
will automatically create a repository proxy for you that adds implementations of finder methods you specify on an
|
||||
interface.
|
||||
|
||||
To create a repository on top of a `User` entity, all you need to write is:
|
||||
To create a repository on top of a `UserInfo` entity, all you need to write is:
|
||||
|
||||
```java
|
||||
public interface UserRepository extends CrudRepository<User, String> {
|
||||
public interface UserRepository extends CrudRepository<UserInfo, String> {
|
||||
|
||||
/**
|
||||
* Return all users emitted by the view user/adults
|
||||
* Return all users emitted by the view userInfo/adults
|
||||
*/
|
||||
@View
|
||||
List<User> findAdults();
|
||||
List<UserInfo> findAdults();
|
||||
|
||||
/**
|
||||
* Find all users matching the last name.
|
||||
*/
|
||||
@View(viewName="lastNames")
|
||||
List<User> findByLastname(String lastName);
|
||||
List<UserInfo> findByLastname(String lastName);
|
||||
|
||||
/**
|
||||
* Find all the users whose first name contains the word.
|
||||
*/
|
||||
List<User> findByFirstnameContains(String word);
|
||||
List<UserInfo> findByFirstnameContains(String word);
|
||||
|
||||
}
|
||||
```
|
||||
@@ -104,7 +104,7 @@ Once you get a reference to that repository bean, you'll find a lot of methods t
|
||||
entity. In addition to the ones provided through the `CrudRepository`, you can add your own methods as well.
|
||||
|
||||
In general, every CRUD method that does not depend on a single key (like `findById`) needs a backing View, `all` on the
|
||||
server side (the design document is by default expected to be the uncapitalized name of the entity, like `user`).
|
||||
server side (the design document is by default expected to be the uncapitalized name of the entity, like `userInfo`).
|
||||
|
||||
## Custom Repository Methods and Views
|
||||
Finder methods you define, if annotated with `@View`, also are backed by views. Either you want to return all items from
|
||||
@@ -112,7 +112,7 @@ these views and you can let the method name reflect the view name (like in `find
|
||||
`adults` view), or provide simple criteria (you explicitly specify the `viewName` and let the method name determine your
|
||||
criteria, like in `findByLastname`).
|
||||
|
||||
In the example above, it assumes you have a view named `findByLastname` in the `user` design document. You
|
||||
In the example above, it assumes you have a view named `findByLastname` in the `userInfo` design document. You
|
||||
can customize the view and design document name through the `@View` annotation. Also make sure you publish them into
|
||||
production before accessing it.
|
||||
|
||||
@@ -120,7 +120,7 @@ This is an example view for the `findByLastname` method:
|
||||
|
||||
```javascript
|
||||
function (doc, meta) {
|
||||
if(doc._class == "com.example.entity.User" && doc.lastname) {
|
||||
if(doc._class == "com.example.entity.UserInfo" && doc.lastname) {
|
||||
emit(doc.lastname, null);
|
||||
}
|
||||
}
|
||||
@@ -134,7 +134,7 @@ function):
|
||||
|
||||
```javascript
|
||||
function (doc, meta) {
|
||||
if(doc._class == "com.example.entity.User") {
|
||||
if(doc._class == "com.example.entity.UserInfo") {
|
||||
emit(null, null);
|
||||
}
|
||||
}
|
||||
@@ -148,13 +148,13 @@ This is the default repository query mechanism, so the associated `@Query` annot
|
||||
like:
|
||||
|
||||
```java
|
||||
public interface UserRepository extends CrudRepository<User, String> {
|
||||
public interface UserRepository extends CrudRepository<UserInfo, String> {
|
||||
|
||||
/**
|
||||
* Advanced querying with N1QL derivation
|
||||
*/
|
||||
@View
|
||||
List<User> findByLastnameEqualsIgnoreCaseAndFirstnameStartsWithAndIsAdultTrue(String lastName, String fnamePrefix);
|
||||
List<UserInfo> findByLastnameEqualsIgnoreCaseAndFirstnameStartsWithAndIsAdultTrue(String lastName, String fnamePrefix);
|
||||
}
|
||||
```
|
||||
|
||||
@@ -169,7 +169,7 @@ placeholder to make sure all necessary fields and metadata are selected by N1QL:
|
||||
|
||||
```java
|
||||
@Query("$SELECT_ENTITY$ WHERE firstname LIKE "%ck%"
|
||||
List<User> findPatrickAndJackAmongOthers();
|
||||
List<UserInfo> findPatrickAndJackAmongOthers();
|
||||
```
|
||||
|
||||
## Using The Repository
|
||||
@@ -232,12 +232,12 @@ public class MyService {
|
||||
public void doWork() {
|
||||
userRepository.deleteAll();
|
||||
|
||||
User user = new User();
|
||||
user.setLastname("Jackson");
|
||||
UserInfo userInfo = new UserInfo();
|
||||
UserInfo.setLastname("Jackson");
|
||||
|
||||
user = userRepository.save(user);
|
||||
UserInfo = userRepository.save(userInfo);
|
||||
|
||||
List<User> allJacksons = userRepository.findByLastname("Jackson");
|
||||
List<UserInfo> allJacksons = userRepository.findByLastname("Jackson");
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
@@ -33,15 +33,15 @@ XML-based configuration is also available:
|
||||
[[couchbase.repository.usage]]
|
||||
== Usage
|
||||
|
||||
In the simplest case, your repository will extend the `CrudRepository<T, String>`, where T is the entity that you want to expose. Let's look at a repository for a user:
|
||||
In the simplest case, your repository will extend the `CrudRepository<T, String>`, where T is the entity that you want to expose. Let's look at a repository for a UserInfo:
|
||||
|
||||
.A User repository
|
||||
.A UserInfo repository
|
||||
====
|
||||
[source,java]
|
||||
----
|
||||
import org.springframework.data.repository.CrudRepository;
|
||||
|
||||
public interface UserRepository extends CrudRepository<User, String> {
|
||||
public interface UserRepository extends CrudRepository<UserInfo, String> {
|
||||
}
|
||||
----
|
||||
====
|
||||
@@ -56,22 +56,22 @@ Now, let's imagine we `@Autowire` the `UserRepository` to a class that makes use
|
||||
| Method
|
||||
| Description
|
||||
|
||||
| User save(User entity)
|
||||
| UserInfo save(UserInfo entity)
|
||||
| Save the given entity.
|
||||
|
||||
| Iterable<User> save(Iterable<User> entity)
|
||||
| Iterable<UserInfo> save(Iterable<UserInfo> entity)
|
||||
| Save the list of entities.
|
||||
|
||||
| User findOne(String id)
|
||||
| UserInfo findOne(String id)
|
||||
| Find a entity by its unique id.
|
||||
|
||||
| boolean exists(String id)
|
||||
| Check if a given entity exists by its unique id.
|
||||
|
||||
| Iterable<User> findAll() (*)
|
||||
| Iterable<UserInfo> findAll() (*)
|
||||
| Find all entities by this type in the bucket.
|
||||
|
||||
| Iterable<User> findAll(Iterable<String> ids)
|
||||
| Iterable<UserInfo> findAll(Iterable<String> ids)
|
||||
| Find all entities by this type and the given list of ids.
|
||||
|
||||
| long count() (*)
|
||||
@@ -80,10 +80,10 @@ Now, let's imagine we `@Autowire` the `UserRepository` to a class that makes use
|
||||
| void delete(String id)
|
||||
| Delete the entity by its id.
|
||||
|
||||
| void delete(User entity)
|
||||
| void delete(UserInfo entity)
|
||||
| Delete the entity.
|
||||
|
||||
| void delete(Iterable<User> entities)
|
||||
| void delete(Iterable<UserInfo> entities)
|
||||
| Delete all given entities.
|
||||
|
||||
| void deleteAll() (*)
|
||||
@@ -106,16 +106,16 @@ WARNING: If it is detected at configuration time that the cluster doesn't suppor
|
||||
|
||||
Here is an example:
|
||||
|
||||
.An extended User repository with N1QL queries
|
||||
.An extended UserInfo repository with N1QL queries
|
||||
====
|
||||
[source,java]
|
||||
----
|
||||
public interface UserRepository extends CrudRepository<User, String> {
|
||||
public interface UserRepository extends CrudRepository<UserInfo, String> {
|
||||
|
||||
@Query("$SELECT_ENTITY$ WHERE role = 'admin'")
|
||||
List<User> findAllAdmins();
|
||||
List<UserInfo> findAllAdmins();
|
||||
|
||||
List<User> findByFirstname(String fname);
|
||||
List<UserInfo> findByFirstname(String fname);
|
||||
}
|
||||
----
|
||||
====
|
||||
@@ -174,7 +174,7 @@ IMPORTANT: This is only true for the methods directly defined by the `CrudReposi
|
||||
|
||||
To cover the basic CRUD methods from the `CrudRepository`, one view needs to be implemented in Couchbase Server. It basically returns all documents for the specific entity and also adds the optional reduce function `_count`.
|
||||
|
||||
Since every view has a design document and view name, by convention we default to `all` as the view name and the lower-cased entity name as the design document name. So if your entity is named `User`, then the code expects the `all` view in the `user` design document. It needs to look like this:
|
||||
Since every view has a design document and view name, by convention we default to `all` as the view name and the uncapitalized (lowercase first letter) entity name as the design document name. So if your entity is named `UserInfo`, then the code expects the `all` view in the `userInfo` design document. It needs to look like this:
|
||||
|
||||
.The all view map function
|
||||
====
|
||||
@@ -182,7 +182,7 @@ Since every view has a design document and view name, by convention we default t
|
||||
----
|
||||
// do not forget the _count reduce function!
|
||||
function (doc, meta) {
|
||||
if (doc._class == "namespace.to.entity.User") {
|
||||
if (doc._class == "namespace.to.entity.UserInfo") {
|
||||
emit(null, null);
|
||||
}
|
||||
}
|
||||
@@ -204,29 +204,29 @@ In `2.0`, since N1QL has been introduced as a more powerful concept, view-backed
|
||||
- View based query derivation is limited to a few keywords and only works on simple keys (not compound keys like `[ age, fname ]`).
|
||||
- View based query derivation still needs you to include *one* valid property before keywords in the method name.
|
||||
|
||||
.An extended User repository with View queries
|
||||
.An extended UserInfo repository with View queries
|
||||
====
|
||||
[source,java]
|
||||
----
|
||||
public interface UserRepository extends CrudRepository<User, String> {
|
||||
public interface UserRepository extends CrudRepository<UserInfo, String> {
|
||||
|
||||
@View
|
||||
List<User> findAllAdmins();
|
||||
List<UserInfo> findAllAdmins();
|
||||
|
||||
@View(viewName="firstNames")
|
||||
List<User> findByFirstnameStartingWith(String fnamePrefix);
|
||||
List<UserInfo> findByFirstnameStartingWith(String fnamePrefix);
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
Implementing your custom repository finder methods also needs backing views. The `findAllAdmins` guesses to use the `allAdmins` view in the `user` design document, by convention. Imagine we have a field on our entity which looks like `boolean isAdmin`. We can write a view like this to expose them (we don't need a reduce function for this one, unless you plan to call one by prefixing your method with `count` instead of `find`!):
|
||||
Implementing your custom repository finder methods also needs backing views. The `findAllAdmins` guesses to use the `allAdmins` view in the `userInfo` design document, by convention. Imagine we have a field on our entity which looks like `boolean isAdmin`. We can write a view like this to expose them (we don't need a reduce function for this one, unless you plan to call one by prefixing your method with `count` instead of `find`!):
|
||||
|
||||
.The allAdmins map function
|
||||
====
|
||||
[source,javascript]
|
||||
----
|
||||
function (doc, meta) {
|
||||
if (doc._class == "namespace.to.entity.User" && doc.isAdmin) {
|
||||
if (doc._class == "namespace.to.entity.UserInfo" && doc.isAdmin) {
|
||||
emit(null, null);
|
||||
}
|
||||
}
|
||||
@@ -240,14 +240,14 @@ By now, we've never actually customized our view at query time. This is where th
|
||||
[source,javascript]
|
||||
----
|
||||
function (doc, meta) {
|
||||
if (doc._class == "namespace.to.entity.User") {
|
||||
if (doc._class == "namespace.to.entity.UserInfo") {
|
||||
emit(doc.firstname, null);
|
||||
}
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
This view not only emits the document id, but also the firstname of every user as the key. We can now run a `ViewQuery` which returns us all users with a firstname of "Michael" or "Michele".
|
||||
This view not only emits the document id, but also the firstname of every UserInfo as the key. We can now run a `ViewQuery` which returns us all users with a firstname of "Michael" or "Michele".
|
||||
|
||||
.Query a repository method with custom params.
|
||||
====
|
||||
@@ -257,7 +257,7 @@ This view not only emits the document id, but also the firstname of every user a
|
||||
UserRepository repo = ctx.getBean(UserRepository.class);
|
||||
|
||||
// Find all users with first name starting with "Mich"
|
||||
List<User> users = repo.findByFirstnameStartingWith("Mich");
|
||||
List<UserInfo> users = repo.findByFirstnameStartingWith("Mich");
|
||||
----
|
||||
====
|
||||
|
||||
|
||||
@@ -30,6 +30,7 @@ import org.springframework.data.couchbase.core.view.View;
|
||||
import org.springframework.data.couchbase.repository.CouchbaseRepository;
|
||||
import org.springframework.data.couchbase.repository.query.CouchbaseEntityInformation;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Repository base implementation for Couchbase.
|
||||
@@ -205,7 +206,7 @@ public class SimpleCouchbaseRepository<T, ID extends Serializable> implements Co
|
||||
* @return ResolvedView containing the designDocument and viewName.
|
||||
*/
|
||||
private ResolvedView determineView() {
|
||||
String designDocument = entityInformation.getJavaType().getSimpleName().toLowerCase();
|
||||
String designDocument = StringUtils.uncapitalize(entityInformation.getJavaType().getSimpleName());
|
||||
String viewName = "all";
|
||||
|
||||
final View view = viewMetadataProvider.getView();
|
||||
|
||||
Reference in New Issue
Block a user