• 一站式SpringBoot for NoSQL Study Tutorial 开发教程学习手册


    SpringBoot2.0 + NoSQL使用教程,项目名称:“SpringBoot2NoSQL”

    项目地址:

    https://gitee.com/475660/SpringBoot2NoSQL

    项目介绍

    All in one一站式SpringBoot for NoSQL开发教程学习手册。

    含SpringBoot2.0 +:

    1. Redis
    2. Ehcache
    3. MongoDB
    4. ElasticSearch
    5. Cassandra
    6. CouchBase
    7. Solr
    8. Neo4j
    9. Gemfire

    共10种常用NoSQL数据库操作、工具类、演示代码。用于整理日常常用的开发模式,一是作为开发笔记以备我自己日后使用,二是分享出来供大家参考。

    重点介绍Redis、MongoDB、ElasticSeach、Cassandra四种数据库,因为它们是各自领域的领先者(分别是KV缓存、文档数据库、搜索数据库、列数据库)。

    另还准备新开一个项目用于介绍Hadoop家族的大数据开发,将命名为“SpringBoot2Hadoop”

    Redis for SpringBoot 开发介绍

    内容:

    • SpringBoot配置、控制器、Repository Crud;
    • string、list、set、zset、hash操作;
    • 同步、异步操作;
    • 管道批处理;
    • 分布式对象操作:对象桶Object Bucket、二进制流Binary Stream、原子类型、发布订阅、HyperLogLog分布式基数估计算法等;分布式锁;
    • 分布式集合操作:哈希、多值哈希、集合、排序集合、队列(双端、阻塞、有界、公平、延迟、优先)
    • 性能测试、内存监控
    • 注意:在启动SpringBoot前要先启动Redis服务。
    application.properties配置:
    # Redis
    # Redis数据库索引(默认为0)
    spring.redis.database=0
    spring.redis.host=127.0.0.1
    spring.redis.port=6379
    #spring.redis.password=123
    # 连接池最大连接数(使用负值表示没有限制)
    spring.redis.pool.max-active=60
    # 连接池中的最大空闲连接
    spring.redis.pool.max-idle=30
    # 连接池最大阻塞等待时间(使用负值表示没有限制)
    spring.redis.pool.max-wait=-1
    # 连接池中的最小空闲连接
    spring.redis.pool.min-idle=0
    
    #redisson配置
    #redis链接地址
    spring.redisson.address=redis://127.0.0.1:6379
    ...
    

    因为我们还使用了Redisson作为客户端,还需RedissonConfig

    @ConfigurationProperties(prefix = "spring.redisson")
    @Configuration
    public class RedissonConfig{
    ...
    

    Spring官方默认支持Lettuce、Jedis客户端,Redis官方的推荐客户端是Redisson,因为Redison提供了诸多分布式的集合工具(这对单机到分布式的扩展非常有益)以及优异的性能,所以非常值得使用Redisson客户端。Spring Boot是一个平台,不必受限于它。我们在代码中配置Redisson连接的模式是单机模式,如想配置集群模式和哨兵模式,请参考官方wiki: https://github.com/redisson/redisson/wiki/

    模型Model:

    见xy.SpringBoot2NoSQL.model.Redis.User

    public class User implements Serializable{
    
        private String login;       
        private String fullName;
        ...
    

    这完全是一个简单POJO java类.使用登录名(login)作为关键字段。

    数据层repository:

    xy.SpringBoot2NoSQL.repository.Redis.ObjectRepository

    以及

    xy.SpringBoot2NoSQL.repository.Redis.UserRepository

    分别是Object类型转换操作的数据类,和泛型User数据操作。 CRUD操作是RedisTemplate中提供了几个常用的单例对象:

    两者都是扩展自org.springframework.data.redis.core.ValueOperations<K, V> ,全面满足Redis的5大数据结构外,还提供了如地理位置、计数估计HyperLogLog操作。如:

    private @Nullable ValueOperations<K, V> valueOps;//KV操作
    private @Nullable ListOperations<K, V> listOps;//列表
    private @Nullable SetOperations<K, V> setOps;//无排序集合
    private @Nullable ZSetOperations<K, V> zSetOps;//计分排序集合
    private @Nullable GeoOperations<K, V> geoOps;//用于地理位置
    private @Nullable HyperLogLogOperations<K, V> hllOps;//基数估值
    ...
    @Override
    public ValueOperations<K, V> opsForValue() {
    
        if (valueOps == null) {
            valueOps = new DefaultValueOperations<>(this);
        }
        return valueOps;
    }
    ...
    @Override
    public ZSetOperations<K, V> opsForZSet() {
    
        if (zSetOps == null) {
            zSetOps = new DefaultZSetOperations<>(this);
        }
        return zSetOps;
    }
    ...
    

    在RedisTemplate中,已经提供了一个工厂方法:opsForValue()。这个方法会返回一个默认的操作类。另外,我们可以直接通过注解@Resource(name = “redisTemplate”)来进行注入。

    控制器controller:

    见xy.SpringBoot2NoSQL.controller.Redis.RedisDataController

    @RestController
    @RequestMapping("/redis")
    public class RedisDataController {
    
        @Autowired
        ObjectRepository objRepository;
        @Autowired
        StringStringRepository stringStringRepository;
    
        @RequestMapping("/add/{name}")
        public String getRecognition(@PathVariable("name") String name){
            User user = new User(name,name);
            objRepository.save(user);
    
            return "add success.";
        }
    
        @RequestMapping("/user/{name}")
        public User getUser(@PathVariable("name") String name){
            return (User)objRepository.get(name);
    
        }
    }
    

    具体代码不再赘述。 另外,提供了Redisson的控制器:

    xy.SpringBoot2NoSQL.controller.Redis.RedissonController

    RedissonController演示了同步异步操作、分布式集合(哈希、多值哈希、集合、排序集合、队列)、本地缓存、对象桶Object Bucket、二进制流Binary Stream、原子类型、发布订阅、HyperLogLog分布式基数估计算法、累加器、元素淘汰、事件监听、分布式锁、异步批量操作等。

    比如本地缓存操作:

        @RequestMapping("/getLocalCachedMap/{name}/{key}")
        public String getLocalCachedMap(@PathVariable("name") String name,@PathVariable("key") String key){
    
            LocalCachedMapOptions<Object, Object> options = LocalCachedMapOptions.defaults()
                    .evictionPolicy(LocalCachedMapOptions.EvictionPolicy.LFU)
                    .cacheSize(100)
                    .syncStrategy(LocalCachedMapOptions.SyncStrategy.UPDATE) //同步缓存
                    .timeToLive(10, TimeUnit.SECONDS)
                    .maxIdle(10, TimeUnit.SECONDS);
    
            RLocalCachedMap<Object, Object> map = redisson.getLocalCachedMap(name,options);     
            map.put(key, "测试值");
            String result = (String)map.get(key);
            return result;
        }
    
    运行效果

    Bucket对象桶操作:

    批量操作:

    有界阻塞队列操作:

    更多详细介绍

    正在写作...

    Ehcache for SpringBoot 开发介绍

    application.properties配置:
    # ehcache
    spring.cache.type=ehcache
    spring.cache.ehcache.config=classpath:ehcache.xml
    

    ehcache.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd"
             updateCheck="false"
             >
        <diskStore path="myCache.ehcache"/>
        <defaultCache
                eternal="true"
                maxElementsInMemory="1000"
                overflowToDisk="true"
                diskPersistent="true"
                timeToIdleSeconds="0"
                timeToLiveSeconds="600"
                memoryStoreEvictionPolicy="LRU" />
    
        <!-- 这里的 users 缓存空间是为了下面的 demo 做准备 -->
        <!-- maxElementsInMemory :cache 中最多可以存放的元素的数量。如果放入cache中的元素超过这个数值,有两种情况:
         1、若overflowToDisk的属性值为true,会将cache中多出的元素放入磁盘文件中。
         2、若overflowToDisk的属性值为false,会根据memoryStoreEvictionPolicy的策略替换cache中原有的元素。-->
    
        <cache
                name="users"
                eternal="true"
                maxElementsInMemory="1000"
                overflowToDisk="true"
                diskPersistent="true"
                timeToIdleSeconds="0"
                timeToLiveSeconds="300"
                memoryStoreEvictionPolicy="LRU" />
    </ehcache>
    
    模型Model:

    见xy.SpringBoot2NoSQL.model.User 这完全是一个简单POJO java类.使用登录名(login)作为关键字段。

    public class User implements Serializable{
    
        private String login;       
        private String fullName;
        ...
    
    数据服务层Service:

    见xy.SpringBoot2NoSQL.service.Ehcache.UserService

    演示简单直接,并没有repository。 getUser() 方法演示了缓存根据配置存在于JVM堆、堆外、磁盘持久化的各种情况。

    控制器controller:

    见xy.SpringBoot2NoSQL.controller.Ehcache.EhcacheDataController

    运行效果

    运行控制器操作:

    持久化到本地磁盘:

    更多详细介绍

    正在写作...

    MongoDB for SpringBoot 开发介绍

    application.properties配置:
    # MONGODB 
    spring.data.mongodb.host=127.0.0.1
    spring.data.mongodb.port=27017
    spring.data.mongodb.database=test
    
    模型Model:

    见xy.SpringBoot2NoSQL.model.Mongo.Person

    @Document 
    public class Person {
        @Id
        private String id;
        private String name;
        private Integer age;
        @Field("locs")
        private Collection<Location> locations =  new LinkedHashSet<Location>();
        @DBRef  
        Department department;
    

    @Document是org.springframework.data.mongodb.core.mapping.Document的注解。

    @Id是定义主键。

    @Field("locs")是定义文档内部对象,在这里是Collection

    @DBRef是链接到外表,Department是链接的表,有点像关系数据库的Inner Join,以Department的id关联。

    数据层repository:

    见xy.SpringBoot2NoSQL.repository.Mongo.PersonRepository

    继承MongoRepository<T, TD>接口,其中T为仓库保存的bean类,TD为该bean的唯一标识的类型,一般为ObjectId。之后在service中注入该接口就可以使用,无需实现里面的方法,spring会根据定义的规则自动生成。

    import org.springframework.data.domain.Page;
    import org.springframework.data.domain.Pageable;
    import org.springframework.data.mongodb.repository.MongoRepository;
    import org.springframework.data.mongodb.repository.Query;
    import xy.SpringBoot2NoSQL.model.Mongo.Person;
    import java.util.List;
    
    public interface PersonRepository extends MongoRepository<Person, String> {
    
        Person findByName(String name);
    
        @Query("{'age': { '$lt' : ?0}}")
        List<Person> withQueryFindByAge(Integer age);
    
        Page<Person> findAll(Pageable pageable);
    
    }
    

    自定义查询方法,还可以使用格式为“findBy+字段名+方法后缀”,方法传进的参数即字段的值,此外还支持分页查询,通过传进一个Pageable对象,返回Page集合。 如查询大于age的数据:

       public Page<Product> findByAgeGreaterThan(int age,Pageable page) ;
    

    也可以使用mongodb原生查询语句,使用@Query注解,如:

        @Query("{'age': { '$lt' : ?0}}")
        List<Person> withQueryFindByAge(Integer age);
    
    //大于
    {"age" : {"$gt" : age}}     
    //小于
    {"age" : {"$lt" : age}}
    //之间
    findByAgeBetween(int from, int to) 
    {"age" : {"$gt" : from, "$lt" : to}}
    //非空
    findByFirstnameNotNull() 
    {"age" : {"$ne" : null}}
    //模糊查询
    findByFirstnameLike(String name) 
    {"age" : age} ( age as regex)
    //非
    findByFirstnameNot(String name) 
    {"age" : {"$ne" : name}}
    
    控制器controller:

    见xy.SpringBoot2NoSQL.controller.Mongo.MongoDataController

    @RestController
    @RequestMapping("/mongo")
    public class MongoDataController {
    
        @Autowired
        PersonRepository personRepository;
        @Autowired
        DepartmentRepository departmentRepository;
    
        @RequestMapping("/persons/{name}")
        public Person getPerson(@PathVariable("name") String name){
            return personRepository.findByName(name);
        }
    
        @GetMapping("findAll")
        public List<Person> getUserList() {
            List<Person> userInfoList = personRepository.findAll();
            return userInfoList;
        }
    
        @GetMapping("insert")
        public Person insert(Long id, String username, String password) {
            Person user = new Person("test2",22);       
            return personRepository.insert(user);
        }
    
        @DeleteMapping("/colleagues/{name}")
        public ResponseEntity<String> deleteColleague(@PathVariable  String name){
            Person person = personRepository.findByName(name);
            if(person!=null) {
                personRepository.delete(person);
                return new ResponseEntity<>(HttpStatus.ACCEPTED);
            }
            return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
        }
        ...
    

    具体CRUD不再赘述。

    运行效果

    保存操作:

    保存结果:

    Query查询:

    更多详细介绍

    正在写作...

    ElasticSearch for SpringBoot 开发介绍

    application.properties配置:
    # elasticsearch
    #节点名字,默认elasticsearch
    spring.data.elasticsearch.cluster-name=elasticsearch
    # 节点地址,多个节点用逗号隔开
    spring.data.elasticsearch.cluster-nodes=127.0.0.1:9300
    #spring.data.elasticsearch.local=false
    spring.data.elasticsearch.repositories.enable=true
    
    模型Model:

    见xy.SpringBoot2NoSQL.model.ElasticSearch.Product

    @Document(indexName = "book",type = "book" , shards = 1, replicas = 0,  refreshInterval = "-1")
    public class Product {
        @Id
        private String id;
        private String name;
    ...
    

    Elasticsearch是面向文档(document oriented)的,这意味着它可以存储整个对象或文档(document)。然而它不仅仅是存储,还会索引(index)每个文档的内容使之可以被搜索。在Elasticsearch中,你可以对文档(而非成行成列的数据)进行索引、搜索、排序、过滤。

    在Elasticsearch中存储数据的行为就叫做索引(indexing),不过在索引之前,我们需要明确数据应该存储在哪里。 在Elasticsearch中,文档归属于一种类型(type),这里是Classname(即book),而这些类型存在于索引(index)中,我们可以画一些简单的对比图来类比传统关系型数据库:

    Relational DB -> Databases -> Tables -> Rows -> Columns
    Elasticsearch -> Indices   -> Types  -> Documents -> Fields
    

    Elasticsearch集群可以包含多个索引(indices)(数据库),每一个索引可以包含多个类型(types)(表),每一个类型包含多个文档(documents)(行),然后每个文档包含多个字段(Fields)(列,比如name、age...)。文档中的所有字段都会被索引(拥有一个倒排索引),只有这样他们才是可被搜索的。注意:传统数据库为特定列增加一个索引,一般使用B-Tree索引,Elasticsearch和Lucene使用一种叫做倒排索引(inverted index)的数据结构。

    数据层repository:

    见xy.SpringBoot2NoSQL.repository.ElasticSearch.SampleProductRepository

    public interface SampleProductRepository extends ElasticsearchRepository<Product,String> {
        List<Product> findByName(String name);
        List<Product> findByDescription(String description);
        List<Product> findByName(String name, Pageable pageable);
        List<Product> findByNameAndId(String name, String id);
    }
    

    通过继承ElasticsearchRepository来完成基本的CRUD及分页操作的,和普通的JPA没有什么区别。ElasticsearchRepository继承了ElasticsearchCrudRepository extends PagingAndSortingRepository。

    另外还可以使用ElasticSearchTemplate,ElasticSearchTemplate更多是对ESRepository的补充,里面提供了一些更底层的方法,主要是一些查询相关的,同样是构建各种SearchQuery条件。比如我们经常需要往ElasticSearch中插入大量的测试数据来完成测试搜索,一条一条插肯定是不行的,ES提供了批量插入数据的功能——bulk。 JPA的save方法也可以save(List)批量插值,但适用于小数据量,要完成超大数据的插入就要用ES自带的bulk了,可以迅速插入百万级的数据。 在ElasticSearchTemplate里也提供了对应的方法。

    控制器controller:

    用于CRUD操作:

    xy.SpringBoot2NoSQL.controller.ElasticSearch.ESDataController

    用于查询操作:

    xy.SpringBoot2NoSQL.controller.ElasticSearch.ESSearchController

    其中matchQuery、fuzzyQuery、termsQuery等查询的区别可见:

    @GetMapping("searchProduct/{key}/{value}/{searchtype}")
    public Page<Product> searchProduct(@PathVariable String key,@PathVariable String value, @PathVariable String searchtype) {
        Page<Product> products = null;
    
        if (searchtype.equals("matchQuery")) {
            products = sampleProductRepository.search(ESSearchUtil.matchQuery(key, value), PageRequest.of(0, 5));
        }
    
        if (searchtype.equals("matchPhraseQuery")) {
            products = sampleProductRepository.search(ESSearchUtil.matchPhraseQuery(key, value), PageRequest.of(0, 5));
        }               
    
        if (searchtype.equals("fuzzyQuery")) {
            products = sampleProductRepository.search(ESSearchUtil.fuzzyQuery(key, value), PageRequest.of(0, 5));
        }
    
        if (searchtype.equals("termsQuery")) {
            products = sampleProductRepository.search(ESSearchUtil.termsQuery(key, value), PageRequest.of(0, 5));
        }
    
        return products;
    }
    

    组合查询:

    public QueryBuilder getBoolQuery() {
    
        return QueryBuilders.boolQuery()
                .must(QueryBuilders.matchPhraseQuery("name", "测试产品1"))
                //.mustNot(QueryBuilders.termQuery("enabled", true));
                .must(QueryBuilders.matchPhraseQuery("enabled", true));
    }
    
    更多详细介绍

    正在写作...

    Cassandra for SpringBoot 开发介绍

    内容
    • SpringBoot配置、控制器、Repository Crud;
    • 使用前需要先建表,建表的脚本见“脚本”》“Cassandra”》“建库脚本.txt”
    • 注意:如果是3.9版本的Win64的DataStax-DDC版本安装后,是无法启动服务的,需要修改配置文件,配置cdcrawdirectory类似如下: cdcrawdirectory: "你的cdcraw目录" ,如果是2.X版不存在这个问题。
    • 注意:在启动SpringBoot前必须先启动Cassandra服务。
    配置:

    cassandra.properties

    #cassandra.properties
    cassandra.contactpoints=127.0.0.1
    cassandra.port=9042
    cassandra.keyspace=mydb
    

    CassandraConfig类

    @Configuration
    @PropertySource(value = { "classpath:cassandra.properties" })
    @EnableCassandraRepositories(basePackages = "xy.SpringBoot2NoSQL.repository.Cassandra")
    public class CassandraConfig extends AbstractCassandraConfiguration {
        @Autowired
        private Environment environment;
    
        @Override
        protected String getKeyspaceName() {
            return environment.getProperty("cassandra.keyspace");
        }
    
        @Override
        @Bean
        public CassandraClusterFactoryBean cluster() {
            ...     
        }
    
        @Override
        @Bean
        public CassandraMappingContext cassandraMapping() throws ClassNotFoundException {
            ...     
        }
    
    }
    
    模型Model:
    @Table
    public class Customer {
    
    @PrimaryKey
    private String id;
    private String firstname; 
    ...
    get、set
    ...   
    

    @Table定义了一个持久化的 Cassandra表,@PrimaryKey指定了主键字段,PrimaryKey是Cassandra中用于获取一行数据的key依据。 可以把Cassandra的数据结构理解为Map<PrimaryKey,SortedMap<ColumnKey,Value>>

    主要语句是:

    CREATE TABLE customer(
         id text PRIMARY KEY,...
    

    是不是有点像关系数据库? 如果想设置自增的key,可以用SERIAL替代text

    数据层repository:
    public interface CustomerRepository extends CassandraRepository<Customer, String> {
    
    @Query(value="SELECT * FROM customer WHERE firstname=?0")
    public List<Customer> findByFirstname(String firstname);
    
    @Query("SELECT * FROM customer WHERE age > ?0")
    public List<Customer> findCustomerHasAgeGreaterThan(int age);
    
    @AllowFiltering
    public List<Customer> findByLastname(String lastname);
    
    @AllowFiltering
    public List<Customer> findByAgeGreaterThan(int age);
    }   
    

    和CrudRepository的使用和扩展一样,增删改查一应俱全了,不再赘述。 CassandraRepository<Customer, String>继承于org.springframework.data.repository的CrudRepository<T, ID> 其中ID是primary key的类型,支持单一的key,如果是复合主键(compound primary key),则需要使用{@link MapId}手动定义键值使用。 @AllowFiltering用于扩展查询,他的作用是不使用@Query注解,而直接使用字段名来查询,还支持大于、小于等操作,但@Query还是来的更直观一些。

    控制器controller:
    @RestController
    @RequestMapping("/cassandra")
    public class CassandraController {
    
    Logger logger = LogManager.getLogger(getClass());
    
    @Autowired
    CustomerRepository customerRepository;
    
    @RequestMapping("/add")
    public String add(){
        customerRepository.deleteAll();     
        Customer cust_1 = new Customer("Test1", "Test1", "Test1", 20);
        Customer cust_2 = new Customer("Test2", "Test2", "Test2", 25);       
        customerRepository.save(cust_1);
        customerRepository.save(cust_2);
    
        return "ok";
    }...
    

    增删改查操作不再赘述。

    运行效果

    范围查询:

    根据Id查询:

    更多详细介绍

    正在写作...

    CouchBase for SpringBoot 开发介绍

    application.properties配置:
    #Couchbase
    spring.couchbase.bootstrap-hosts=127.0.0.1
    spring.couchbase.bucket.name=mydb
    spring.couchbase.bucket.password=123456
    spring.data.couchbase.auto-index=true
    
    模型Model:

    见xy.SpringBoot2NoSQL.model.Couchbase.Customer

    数据层repository:

    见xy.SpringBoot2NoSQL.repository.Couchbase.CouchbaseCustomerRepository

    控制器controller:

    见xy.SpringBoot2NoSQL.controller.Couchbase.CouchbaseController

    更多详细介绍

    正在写作...

    Solr for SpringBoot 开发介绍

    application.properties配置:
    spring.data.solr.host=http://localhost:8983/solr
    
    模型Model:

    见xy.SpringBoot2NoSQL.model.Solr.Customer

    数据层repository:

    见xy.SpringBoot2NoSQL.repository.Solr.SolrCustomerRepository

    控制器controller:

    见xy.SpringBoot2NoSQL.controller.Solr.SolrController

    更多详细介绍

    正在写作...

    Neo4j for SpringBoot 开发介绍

    正在写作...

    Gemfire for SpringBoot 开发介绍

    正在写作...

    Hadoop家族 for SpringBoot 开发介绍

    准备另开一个项目,不在此工程(SpringBoot2NoSQL)中,新项目将命名为“SpringBoot2Hadoop”

    “SpringBoot2NoSQL”项目地址:

    https://gitee.com/475660/SpringBoot2NoSQL

  • 相关阅读:
    INV接口管理器
    取会计科目之数字
    两个有用的oracle数据库运算:intersect和minus运算
    弹出“FRM40400:事务完成:已应用和保存X条记录
    JSP连接数据库
    javaScript JSP HTML Java CSS 注释
    Android开发环境搭建全过程
    用JAVA 实现“生产者-消费者”问题
    路由器如何当交换机使用
    validateJarFile jar not loaded. See Servlet Spec 2.3, section 9.7.2. Offending class: javax/servlet
  • 原文地址:https://www.cnblogs.com/starcrm/p/9667830.html
Copyright © 2020-2023  润新知