Spring-data-mongodb初步使用

前幾天調研了一下spring-data的使用。此處作一下使用的簡單介紹:
在使用關係型數據庫的傳統Java web開發中,咱們一般使用以下層級結構:
輸入圖片說明
Dao層主要完成OR-Mapping的功能,進行數據的存儲。可是在咱們使用Mongo數據庫以後,本來的層級就可能變成了以下:
輸入圖片說明
由於咱們從mongo的數據爲json格式,可使用fastjson與POJO進行相互轉換。
這樣層級設計,開發就能夠能很快地完成,可是形成一些問題:html

  1. 業務邏輯代碼和數據庫操做代碼耦合在一塊兒,較爲難以分離
  2. 加大了單元測試的難度
  3. 結構層次不清晰

如下是理由:java

  1. 上面1和3形成的緣由都是由於函數體變長,業務代碼和數據庫代碼雜糅在一塊兒形成的,出錯時,須要對整個函數進行復驗,確保函數的編寫的正確性。編寫UT時也會形成須要覆蓋的路徑(語句)增多,難度所以增長。
  2. 結構層次不清晰,在分爲Service和Dao層的狀況下,邏輯層級更爲清晰,業務層主作業務,Dao層主作數據庫的CURD。

因此咱們可使用spring-data-mongo來完成dao層的編寫。
如下代碼都是測試經過的,主要注意幾個點:web

  1. 代碼只須要定義成這樣既可,通常的查詢均可以使用這些自動生成的代碼來進行完成
  2. 若是須要添加自定義的方法,在這邊我使用的是JDK8的default關鍵字,直接將實現添加在了接口裏面,實測可用
  3. 啓動時spring會操做字節碼自動生成實現類,因此啓動可能較慢,而且一旦有bug調試起來很麻煩(基本沒法調試)。

接口定義示例:spring

public interface UserRepository extends MongoRepository<User, String> {
    //////////////////////Query/////////////////////
    // Do not recommend using @Query annotation like this
    @Query("{ 'firstname' : ?0, 'password': ?1 }")
    public User findByUsernameAndPassword(String username, String password);

    // find age larger than
    // there are others:
    public List<User> findByAgeGreaterThan(Integer age);
    public List<User> findByAgeLessThan(Integer age);
    public List<User> findByAgeBetween(Integer from, Integer to);
    public List<User> findBySexNot(String sex);
    public List<User> findBySexLike(String sex);
    public List<User> findBySexNotLike(String sex);
    public List<User> findByUsernameNull();
    public List<User> findByUsernameNotNull();

    // find by username
    public User findByUsername(String username);

    // find distinct users by username
    public List<User> findDistinctUserByUsername(String username);
    public List<User> findUserDistinctByUsername(String username);

    // find users by username and age
    public List<User> findByUsernameAndAge(String username, Integer age);

    // find users by username or age
    public List<User> findByUsernameOrAge(String username, Integer age);

    // find users by sex with ignoring cases
    public List<User> findBySexIgnoreCase(String sex, Pageable pageable);

    // find users by sex with order firstname ascending
    public List<User> findBySexOrderByUsernameAsc(String sex);

    // find users by sex with the order sort specfied
    public List<User> findBySex(String sex, Sort sort);

    // find users bys sex with pageable
    public List<User> findBySex(String sex, Pageable pageable);

    // find the first ten results by user sex
    public Slice<User> findTop10BySex(String sex, Sort sort);
    public Slice<User> findFirst10BySex(String sex, Sort sort);

    // other query like Stream Query and Async Query could be
    // found here http://docs.spring.io/spring-data/mongodb/docs/current/reference/html/#repositories.query-methods

    // define the method by ourself
    default User findByUsernameAndPasswordByOwn(String username, String password) {
        MongoOperations ops = DbUtil.getDbUtil().getMongoTemplate();
        User user = ops.findOne(query(where("username").is(username))
                .addCriteria(where("password").is(password)), User.class);
        return user;
    }

    default GroupByResults<User> findUserGroupBySex() {
        GroupByResults<User> results = DbUtil.getDbUtil().getMongoTemplate()
                .group("user", GroupBy.key("sex").initialDocument("{ count: 0 }")
                                .reduceFunction("function(doc, prev) { prev.count += 1 }"),
                User.class);
        return results;
    }

    //////////////////////Delete/////////////////////
    public void deleteByUsername(String username);
    public void removeByUsernameAndAge(String username, Integer age);

    /////////////////////update////////////////////////
    // normally, we use sper.update(), if the method can't meet your demand,
    // you can write the method yourself
    default void updateMultiByUsername(String username, Integer age) {
        MongoOperations ops = DbUtil.getDbUtil().getMongoTemplate();
        // update all the documents whose username atteribute is username
        // and the class need to be User
        ops.updateMulti(query(where("username").is(username)),
                Update.update("age", age), User.class);
    }

    //////////////////save///////////////
    // just use default save(). forget about the others.
}

使用例子:mongodb

@RestController
public class UserController {
    @Autowired
    UserRepository userRepository;

    @RequestMapping("/")
    public String sayHello(String name) {
        return "Hello, " + name;
    }

    @RequestMapping(value="/user", method = RequestMethod.POST)
    public String add(@RequestParam String companyId, @RequestBody User user) {
        user = userRepository.save(user);
        return user.getId();
    }

    @RequestMapping(value = "/user/username", method = RequestMethod.GET)
    public User getUserByUserName(@RequestParam String companyId, @RequestParam String username,
                                  @RequestParam String password) {
        User user;

        user = userRepository.findByUsernameAndPassword(username, password);
        return user;
    }

    @RequestMapping(value="/user/group/sex", method = RequestMethod.GET)
    public GroupByResults<User> groupUserBySex() {
        return userRepository.findUserGroupBySex();
    }
}
相關文章
相關標籤/搜索