SpringBoot对非关系型数据库NoSql的支持

NoSql是对于所有不使用关系作为数据管理的数据库系统的总称,NoSql的特点主要是不使用sql作为查询语言。数据存储也不是固定的表和字段
NoSql数据库主要有文档存储型(MongoDB),图形关系存储型(Neo4j),键值对存储型(Redis)

Spring对MongoDB的支持

Spring对MongoDB的支持主要是通过Spring Data MongoDB来实现的。

Spring Data MongoDB提供的注解支持

  • @Document 映射领域对象与MongoDB的一个文档
  • @Id 映射当前属性是ID
  • @DbRef 当前属性将参考其他文档
  • @Field 为文档的属性定义名称
  • @Version 将当前属性作为版本

数据操作MongoTemplete的支持

MongoTemplete为我们提供了数据放我那和操作的方法,我们还需要为MongoClient和MongoDbFactory来配置数据库连接属性。

    @Bean
    public MongoClient client() throws UnKnownHostException{
    MongoClient client = new MongoClient(new ServerAddress("127.0.0.1",27017))
    }
    @Bean
    public MongoDbFactory mongoDbFactory() throws Exception{
    String database = new MongoClientURI("mongodb://localhost/test").getDatabase();
    return new SimpleMongoDbFactory(client(),database);
    }
    @Bean
    public MongoTemplete mongoTemplete(MongoDbFactory mongoDbFactory)throws UnKnownHostException{
        return new MongoTemplete(mongoDbFactory);
    }

@Repository的支持

Spring提供了类似JpaRepository的支持MongoRepository的支持
在自定义的Repository接口中继承即可

public interface PersonRepository extends MongoRepository<Person,String>{
}

如何开启MongoRepository,则需要在配置类或是Spring的入口类中加入注解@EnableMongoRepository

SpringBoot对MongoDB的支持

springBoot为我们提供了一些默认属性例如默认端口27017,默认服务器为localhost。默认数据库为test等
我们开始使用之前除了上述知识需要掌握以外只需引入spring-boot-starter-data-mongodb依赖外,无需任何其他配置。

SpringBoot+MongoDB实战

首先依然是准备代码

代码准备

pom文件引入

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-mongodb</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

在这里要注意的是,我们这里只是测试MongoDB单数据源的情况,如果要进行多数据源测试,那么需要进行额外的配置,如果这里引入了mysql的依赖。那么程序会报错

Cannot determine embedded database driver class for database type NONE

接下来是实体的准备
Person类

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

    public String getName() {
        return name;
    }

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

    public Integer getAge() {
        return age;
    }

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

    public void setLocations(Collection<Location> locations) {
        this.locations = locations;
    }

    public String getId() {
        return id;
    }

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

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

    }

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

Location类

public class Location {
    private  String place;

    private  String 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;
    }

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

@Document注解映射领域模型和MongoDB的文档
@Id注解表明这个属性为文档的Id
@Field注解此属性在文档中的名称为locs,locations属性将以数组形式存在当前数据记录中

Repository

    Person findByName(String name);

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

从上述方法可见,MongoRepository仍然支持类似于JPA的方法名和Query查询

Controller层

@RestController
public class DataController {
    @Autowired
    PersonRepository personRepository;

    @RequestMapping("/save")
    public  Person save(){
        Person p = new Person("zhaozhen",23);
        Collection<Location> locations = new LinkedHashSet<>();
        Location loc1 =new Location("上海","2012");
        Location loc2 =new Location("合肥","2013");
        Location loc3 =new Location("武汉","2014");
        Location loc4 =new Location("北京","2015");
        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);
    }
}

访问http://localhost:8080/save 可以看到

这里写图片描述

数据已经被保存到MongoDB中(可视化工具为RoboMongo),Mongo的安装请参照:MongoDB学习(三)MongoDB 3.2.8的使用详解
测试两个查询方法的结果如下图
查询年龄

查询姓名


查询姓名

源码地址

Spring对Redis的支持

Redis是一个基于键值对的开源内存数据存储,当然Redis也可以作为数据缓存。Spring 对Redis的支持是通过Spring Data Redis来实现的,SpringData JPA为我们提供了连接相关的connectionFactory和数据操作相关的RedisTemplete。根据Redis的不同的java客户端有如下

connectionFactory划分

  • JedisConnectionFactory ,使用Jedis作为Redis客户端
  • JredisConnectionFactory,使用Jredis作为Redis客户端
  • LettuceConnectionFactory,使用Lettuce作为Redis客户端
  • SrpConnectionFactory,使用Squllara/redis-protocol作为Redis客户端

数据操作相关的RedisTemplete主要分为RedisTemplete和StringRedisTemplete两个模板进行数据操作。前者主要处理对象的数据操作,后者主要处理String类型的数据操作。两种数据操作模板主要有以下方法

操作方法

  • opsForValue 操作只有简单属性的数据
  • opsForList 操作含有List的数据
  • opsForSet 操作含有Set的数据
  • opsForZSet操作含有ZSet(有序的set)的数据
  • opsForHash 操作含有hash的数据

Redis的序列化Serializer

当我们的数据存储到Redis的时候,我们的键值对是通过Serializer序列化到数据库的RedisTemplete默认使用的是JdkSerializationRedisSerializer,StringRedisTemplete默认使用的是StringRedisSerializer,除此之外Spring Data JPA还为我们提供如下Serializer:GenericToStringSerializer,Jackson2JsonRedisSerializer,JacksonJsonRedisSerializer,OxmSerializer.

SpringBoot对Redis的支持

SpringBoot的自动配置为我们自动默认配置了JedisConnectionfactory、RedisTemplete,StringRedisTemplete,让我们可以直接使用Redis作为数据存储。我们也可以在properties文件中以spring.redis开头作为前缀配置Redis的属性。

SpringBoot对Redis的实践

前期准备

首先需要在本机安装Redis 。教程传送门:在windows上搭建Redis环境
然后下载一个Redis管理的可视化工具。例如Redis client或者Redis Desktop Manager

代码准备

实体类

public class Person implements Serializable {
    private  String id;
    private String name;
    private Integer age;

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

    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;
    }
}

Dao层

@Repository
public class PersonDao {
    @Autowired
    StringRedisTemplate stringRedisTemplate;

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

    @Autowired
    RedisTemplate<Object,Object> redisTemplate;
    @Resource(name = "redisTemplate")
    ValueOperations<Object,Object> valueOps;
    //存储字符串类型
    public void stringRedisTempleteDemo(){
        valueOpsStr.set("xx","yy");
    }
    //存储对象类型
    public  void  save(Person person){
        valueOps.set(person.getId(),person);
    }
    //获得字符串
    public  String getString(){
        return  valueOpsStr.get("xx");
    }
    //获取对象类型
    public Person getPerson(){
        return (Person) valueOps.get("1");
    }
}

SpringBoot为我们配置了RedisTemplete。而RedisTemplete使用的是JdkSerializationRedisSerializer(用二进制存储数据)。这个对后续可视化工具的演示不太直接。
我们在此自己配置RedisTemplete并定义Serializer。

入口类

@SpringBootApplication
public class SpringBootRedisApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringBootRedisApplication.class, args);
    }
    @Bean
    @SuppressWarnings({ "rawtypes", "unchecked" })
    public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory)
            throws UnknownHostException {
        RedisTemplate<Object, Object> template = new RedisTemplate<Object, Object>();
        template.setConnectionFactory(redisConnectionFactory);

        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;
    }

}

控制器

@RestController
public class DataController {

    @Autowired
    PersonDao personDao;

    @RequestMapping("/test")
    public void set(){
        Person p = new Person("1",23,"zhaozhen");
        personDao.save(p);
        personDao.stringRedisTempleteDemo();
    }

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

    }
    @RequestMapping("/getPerson")
    public Person getPerson(){
        return  personDao.getPerson();
    }

}

运行之后我们可以看到。访问http://localhost:8080/test 会发现数据可视化中出现了如下数据

这里写图片描述

获取字符数据http://localhost:8080/getStr

这里写图片描述

获取实体数据http://localhost:8080/getPerson

这里写图片描述

代码

总结

本篇博客主要讲解了SpringBoot与两种Nosql数据库的结合,比较简单。后续会继续深入的探讨SpringBoot的知识。希望与大家多交流。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,185评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,445评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,684评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,564评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,681评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,874评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,025评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,761评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,217评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,545评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,694评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,351评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,988评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,778评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,007评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,427评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,580评论 2 349

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,633评论 18 139
  • Spring Boot 参考指南 介绍 转载自:https://www.gitbook.com/book/qbgb...
    毛宇鹏阅读 46,778评论 6 342
  • 越坚持越幸运,只要有希望就尝试多试,这是今天清晨我的感悟! 一般的早晨我去上班,顺路送女儿上学,是我先出门把车开到...
    冯陈陈阅读 413评论 1 2
  • 住了多年宿舍,深知宿舍住宿的种种方便,然而这又是学生党们长期厮守的地方。想必刚刚入学大学的新生小盆友们也体会到了宿...
    一个学习备份阅读 1,503评论 6 30
  • 第一次喝的鸡汤,大概是到现在也流传的那句“当你又瘦又好看,钱包里都是自己努力赚来的钱的时候,你就会恍然大悟,哪有时...
    南瓜不甜_阅读 813评论 0 5