1. 程式人生 > >29-SpringBoot——核心-非關係型資料庫NoSQL

29-SpringBoot——核心-非關係型資料庫NoSQL

SpringBoot核心-非關係型資料庫NoSQL

MongoDB

MongoDB 是一個基於文件( Document )的儲存型的資料瘁,使用面向物件的思想,每一條資料記錄都是文件的物件。Spring 對MongoDB 的支援主要是通過Spring Data MongoDB 來實現的, Spring Data MongoDB 為我們提供瞭如下功能。

Object/Document 對映註解支援

JPA 提供了一套Object/Relation 對映的註解(@Entity 、@Id ),而Spring Data MongoDB 也提供了下圖所示的註解。

這裡寫圖片描述

MongoTemplate

像JdbcTemplate 一樣, Spring Data MongoDB 也為我們提供了一個MongoTemplate,MongoTemplate 為我們提供了資料訪問的方法。我們還需要為MongoClient 以及MongoDbFactory 來配置資料庫連線屬性。

public class MongoConfigSample {
    @Bean
    public MongoClient client () throws Exception {
        return new MongoClient(new ServerAddress("127.0.0.1"
, 27017)); } @Bean public MongoDbFactory mongoDbFactory() throws Exception { String database = new MongoClientURI("mongo://localhost/test").toString(); return new SimpleMongoDbFactory(client(), database); } @Bean public MongoTemplate mongoTemplate() throws Exception { return
new MongoTemplate(mongoDbFactory()); } }

ReRpository 的支援

類似於Spring Data JPA, Spring Data MongoDB 也提供了Repository 的支付,使用方式和Spring Data JPA一致。

public interface PersonRepository extends MongoRepository<Person, String>{
    Person findByName(String name);

    @Query("{'age': ?0}")
    List<Person> withQueryFindByAge(Integer age);
}

類似於Spring Data JPA 的開啟文持方式, MongoDB的Repository 的支援開啟需要在配置類上註解@EnableMongoRepositories 。

Spring Boot 的支援

Spring Boot 對MongoDB 的支援,分別位於org.springframework.boot.autocorifigure.mongo。主要配置資料庫連線、Mongo Template 。我們可以使用以“ spring.data.mongodb ”為字首的屬性來配置MongoDB 相關的資訊。Spring Boot 為我們提供了一些預設屬性,如預設MongoDB 的埠為27017、預設伺服器為local host、預設資料庫為testa Spring Boot 的主要配置如下:

# MONGODB (MongoProperties)
spring.data.mongodb.authentication-database= # Authentication database name.
spring.data.mongodb.database=test # Database name.
spring.data.mongodb.field-naming-strategy= # Fully qualified name of the FieldNamingStrategy to use.
spring.data.mongodb.grid-fs-database= # GridFS database name.
spring.data.mongodb.host=localhost # Mongo server host. Cannot be set with uri.
spring.data.mongodb.password= # Login password of the mongo server. Cannot be set with uri.
spring.data.mongodb.port=27017 # Mongo server port. Cannot be set with uri.
spring.data.mongodb.repositories.enabled=true # Enable Mongo repositories.
spring.data.mongodb.uri=mongodb://localhost/test # Mongo database URI. Cannot be set with host, port and credentials.
spring.data.mongodb.username= # Login user of the mongo server. Cannot be set with uri.

Redis

Red is 是一個基於鍵值對的開源記憶體資料儲存,當然Redis 也可以做資料快取。

Spring 的支援

配置

Spring 對Redis 的支援也是通過Spring Data Redis 來實現的, Spring Data JPA 為我們提供了連線相關的ConnectionFactory 和資料操作相關的RedisTemplate 。在此特別指出, Spring Data Redis 只對Redis 2.6 和2.8 版本做過測試。根據Redis 的不同的Java 客戶端, Spring Data Redis 提供瞭如下的ConnectionFactory:
JedisConnectionF actory :使用Jedis 作為Redis 客戶端。
JredisConnectionF actory:使用Jredis 作為Redis 客戶端。
LcttuceConnectionFactory :使用Lettuce 作為Redis 客戶端。
SrpConnectionFactory:使用Spullara/redis-protocal 作為Redis 客戶端。
配置方式如下:

@Bean
public RedisConnectionFactory redisConnectionFactory() {
    return new JedisConnectionFactory();
}

RedisTemplate 配置方式如下

@Bean
public RedisTemplate<Object, Object> redisTemplate() {
    RedisTemplate<Object, Object> template = new RedisTemplate<>();
    template.setConnectionFactory(redisConnectionFactory());
    return  template;
}

使用

Spring Data Redis 為我們提供了RedisTemplate 和StringRedisTemplate 兩個模板來進行資料操作,其中, StringRedisTemplate 只針對鍵值都是字元型的資料進行操作。RedisTemplate 和StringRedisTemplate 提供的主要資料訪問方法如下。

這裡寫圖片描述

定義Serializer

當我們的資料儲存到Redis 的時候,我們的鍵( key )和值( value )都是通過Spring 提供的Serializer 序列化到資料庫的。RedisTemplate 預設使用的是JdkSerializationRedi’sSerializer,StringRedisTemplate 預設使用的是StringRedisSerializero。

Spring Data JPA 為我們提供了下面的Serializer:

GenericToStringSerializer 、Jackson2JsonRedisSerializer 、JacksonJsonRedisSerializer 、J dkSerializationRedisSerializer、OxmSerializer 、StringRedisSerializer。

Spring Boot 的支援

Spring Boot 對Redis的支援, org.springframework.boot.autoconfigure.redis。RedisAutoConfiguration 為我們預設配置了JedisConnectionFactory 、RedisTemplate 以及StringRedisTemplate ,讓我們可以直接使用Redis 作為資料儲存。RedisProperties 向我們展示了可以使用以“ spring.redis ”為字首的屬性在application.prope此時中配置Redis ,主要屬性如下:

# REDIS (RedisProperties)
spring.redis.cluster.max-redirects= # Maximum number of redirects to follow when executing commands across the cluster.
spring.redis.cluster.nodes= # Comma-separated list of "host:port" pairs to bootstrap from.
spring.redis.database=0 # Database index used by the connection factory.
spring.redis.url= # Connection URL, will override host, port and password (user will be ignored), e.g. redis://user:[email protected]:6379
spring.redis.host=localhost # Redis server host.
spring.redis.password= # Login password of the redis server.
spring.redis.ssl=false # Enable SSL support.
spring.redis.pool.max-active=8 # Max number of connections that can be allocated by the pool at a given time. Use a negative value for no limit.
spring.redis.pool.max-idle=8 # Max number of "idle" connections in the pool. Use a negative value to indicate an unlimited number of idle connections.
spring.redis.pool.max-wait=-1 # Maximum amount of time (in milliseconds) a connection allocation should block before throwing an exception when the pool is exhausted. Use a negative value to block indefinitely.
spring.redis.pool.min-idle=0 # Target for the minimum number of idle connections to maintain in the pool. This setting only has an effect if it is positive.
spring.redis.port=6379 # Redis server port.
spring.redis.sentinel.master= # Name of Redis server.
spring.redis.sentinel.nodes= # Comma-separated list of host:port pairs.
spring.redis.timeout=0 # Connection timeout in milliseconds.

程式碼實現

MongoDB

package com.example.spring.boot.nosql.domain;

/**
 * Author: 王俊超
 * Date: 2017-07-19 07:39
 * All Rights Reserved !!!
 */
public class Location {
    private String place;
    private String year;

    public Location(String place, String year) {
        super();
        this.place = place;
        this.year = year;
    }

    public String getPlace() {
        return place;
    }

    public void setPlace(String place) {
        this.place = place;
    }

    public String getYear() {
        return year;
    }

    public void setYear(String year) {
        this.year = year;
    }
}
package com.example.spring.boot.nosql.domain;

import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;
import org.springframework.data.mongodb.core.mapping.Field;

import java.util.Collection;
import java.util.LinkedHashSet;

/**
 * Author: 王俊超
 * Date: 2017-07-19 07:37
 * All Rights Reserved !!!
 */
@Document //1
public class Person {
    @Id
    private String id;
    private String name;
    private Integer age;
    @Field("locs")
    private Collection<Location> locations =  new LinkedHashSet<Location>();


    public Person(String name, Integer age) {
        super();
        this.name = name;
        this.age = age;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public Collection<Location> getLocations() {
        return locations;
    }

    public void setLocations(Collection<Location> locations) {
        this.locations = locations;
    }
}
package com.example.spring.boot.nosql.dao;

import com.example.spring.boot.nosql.domain.Person;
import org.springframework.data.mongodb.repository.MongoRepository;
import org.springframework.data.mongodb.repository.Query;

import java.util.List;

/**
 * Author: 王俊超
 * Date: 2017-07-19 07:37
 * All Rights Reserved !!!
 */
public interface PersonRepository extends MongoRepository<Person, String>{
    Person findByName(String name);

    @Query("{'age': ?0}")
    List<Person> withQueryFindByAge(Integer age);
}
package com.example.spring.boot.nosql.controller;

import com.example.spring.boot.nosql.dao.PersonRepository;
import com.example.spring.boot.nosql.domain.Location;
import com.example.spring.boot.nosql.domain.Person;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.Collection;
import java.util.LinkedHashSet;
import java.util.List;

/**
 * Author: 王俊超
 * Date: 2017-07-19 07:42
 * All Rights Reserved !!!
 */
@RestController
public class DataController {
    @Autowired
    PersonRepository personRepository;

    @RequestMapping("/save")
    public Person save() {
        Person p = new Person("wjc", 18);
        Collection<Location> locations = new LinkedHashSet<Location>();
        Location loc1 = new Location("長沙", "2009");
        Location loc2 = new Location("合肥", "2010");
        Location loc3 = new Location("廣州", "2011");
        Location loc4 = new Location("深圳", "2012");
        locations.add(loc1);
        locations.add(loc2);
        locations.add(loc3);
        locations.add(loc4);
        p.setLocations(locations);

        return personRepository.save(p);
    }

    @RequestMapping("/q1")
    public Person q1(String name) {
        return personRepository.findByName(name);
    }

    @RequestMapping("/q2")
    public List<Person> q2(Integer age) {
        return personRepository.withQueryFindByAge(age);
    }
}
package com.example.spring.boot.nosql;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

/**
 * Author: 王俊超
 * Date: 2017-07-19 07:43
 * All Rights Reserved !!!
 */
@SpringBootApplication
public class SampleApplication {
    public static void main(String[] args) {
        SpringApplication.run(SampleApplication.class, args);
    }
}

Redis

package com.example.spring.boot.redis.domain;

/**
 * Author: 王俊超
 * Date: 2017-07-19 07:57
 * All Rights Reserved !!!
 */
public class Person {
    private static final long serialVersionUID = 1L;

    private String id;
    private String name;
    private Integer age;

    public Person() {
    }

    public Person(String id, String name, Integer age) {
        this.id = id;
        this.name = name;
        this.age = age;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }
}
package com.example.spring.boot.redis.dao;

import com.example.spring.boot.redis.domain.Person;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Repository;

import javax.annotation.Resource;

/**
 * Author: 王俊超
 * Date: 2017-07-19 07:53
 * All Rights Reserved !!!
 */
@Repository
public class PersonDao {
    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Resource(name = "stringRedisTemplate")
    ValueOperations<String, String> valOpsStr;

    @Autowired
    RedisTemplate<Object, Object> redisTemplate;

    @Resource(name = "redisTemplate")
    ValueOperations<Object, Object> valOps;

    public void stringRedisTemplateDemo(){ //5
        valOpsStr.set("xx", "yy");
    }


    public void save(Person person){ //6
        valOps.set(person.getId(),person);
    }

    public String getString(){//7
        return valOpsStr.get("xx");
    }

    public Person getPerson(){//8
        return (Person) valOps.get("1");
    }
}
package com.example.spring.boot.redis.controller;

import com.example.spring.boot.redis.dao.PersonDao;
import com.example.spring.boot.redis.domain.Person;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * Author: 王俊超
 * Date: 2017-07-19 07:59
 * All Rights Reserved !!!
 */
@RestController
public class DataController {
    @Autowired
    PersonDao personDao;

    @RequestMapping("/set") //1
    public void set() {
        Person person = new Person("1", "wjc", 18);
        personDao.save(person);
        personDao.stringRedisTemplateDemo();
    }

    @RequestMapping("/getStr") //2
    public String getStr() {
        return personDao.getString();
    }

    @RequestMapping("/getPerson") //3
    public Person getPerson() {
        return personDao.getPerson();
    }
}
package com.example.spring.boot.redis;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

/**
 * Author: 王俊超
 * Date: 2017-07-19 08:01
 * All Rights Reserved !!!
 */
@SpringBootApplication
public class SampleApplication {
    public static void main(String[] args) {
        SpringApplication.run(SampleApplication.class, args);
    }
    @Bean
    public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory factory) {
        RedisTemplate<Object, Object> template = new RedisTemplate<Object, Object>();
        template.setConnectionFactory(factory);

        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
        ObjectMapper om = new ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(om);

        template.setValueSerializer(jackson2JsonRedisSerializer); //1
        template.setKeySerializer(new StringRedisSerializer()); //2

        template.afterPropertiesSet();
        return template;

    }
}