diff --git a/README.md b/README.md index 5c39926c..783ba3ed 100644 --- a/README.md +++ b/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 { +public interface UserRepository extends CrudRepository { /** - * Return all users emitted by the view user/adults + * Return all users emitted by the view userInfo/adults */ @View - List findAdults(); + List findAdults(); /** * Find all users matching the last name. */ @View(viewName="lastNames") - List findByLastname(String lastName); + List findByLastname(String lastName); /** * Find all the users whose first name contains the word. */ - List findByFirstnameContains(String word); + List 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 { +public interface UserRepository extends CrudRepository { /** * Advanced querying with N1QL derivation */ @View - List findByLastnameEqualsIgnoreCaseAndFirstnameStartsWithAndIsAdultTrue(String lastName, String fnamePrefix); + List 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 findPatrickAndJackAmongOthers(); +List 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 allJacksons = userRepository.findByLastname("Jackson"); + List allJacksons = userRepository.findByLastname("Jackson"); } } ``` diff --git a/src/main/asciidoc/repository.adoc b/src/main/asciidoc/repository.adoc index b09cff39..00507949 100644 --- a/src/main/asciidoc/repository.adoc +++ b/src/main/asciidoc/repository.adoc @@ -33,15 +33,15 @@ XML-based configuration is also available: [[couchbase.repository.usage]] == Usage -In the simplest case, your repository will extend the `CrudRepository`, 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`, 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 { +public interface UserRepository extends CrudRepository { } ---- ==== @@ -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 save(Iterable entity) +| Iterable save(Iterable 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 findAll() (*) +| Iterable findAll() (*) | Find all entities by this type in the bucket. -| Iterable findAll(Iterable ids) +| Iterable findAll(Iterable 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 entities) +| void delete(Iterable 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 { +public interface UserRepository extends CrudRepository { @Query("$SELECT_ENTITY$ WHERE role = 'admin'") - List findAllAdmins(); + List findAllAdmins(); - List findByFirstname(String fname); + List 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 { +public interface UserRepository extends CrudRepository { @View - List findAllAdmins(); + List findAllAdmins(); @View(viewName="firstNames") - List findByFirstnameStartingWith(String fnamePrefix); + List 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 users = repo.findByFirstnameStartingWith("Mich"); +List users = repo.findByFirstnameStartingWith("Mich"); ---- ==== diff --git a/src/main/java/org/springframework/data/couchbase/repository/support/SimpleCouchbaseRepository.java b/src/main/java/org/springframework/data/couchbase/repository/support/SimpleCouchbaseRepository.java index 50e97488..2e4183be 100644 --- a/src/main/java/org/springframework/data/couchbase/repository/support/SimpleCouchbaseRepository.java +++ b/src/main/java/org/springframework/data/couchbase/repository/support/SimpleCouchbaseRepository.java @@ -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 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();