Faunadb

Faunadb和google spanner都属于云分布式数据库天然支持分片(无需做分表分库操作,一库搞定,当然价格另说),国内的也有比如TiDB  Oceanbase等

本文使用java语言,其他语言可以跳过;有想直接使用的可以参考(无法访问外网,可以搞个吧!!!,有时会遇到网络问题):GitHub - fauna/faunadb-jvm: Scala and Java driver for FaunaDB v4

此文旨在想了解的小伙伴看看(免费使用30天)

本文演示使用的jdk版本为jdk21

目录

1.登录账号

2.了解一下FQL

3. 创建数据库,创建集合

4.点击搜索框中的dashbord进入到控制台然后到控制台创建集合

5. 生成数据库秘钥

6.springboot整合项目

7.实体

8.service及接口

9.属性文件配置属性

10.controller

11.启动后postman试试


1.登录账号

使用github账号或者注册一个

Welcome to Fauna docs - Fauna Documentation

Faunadb_第1张图片

2.了解一下FQL

建议按照图看下去

Faunadb_第2张图片

3. 创建数据库,创建集合

最好是跟着官网文档走

Faunadb_第3张图片

4.点击搜索框中的dashbord进入到控制台然后到控制台创建集合

(参考:使用 Spring Boot 使用 Fauna 和 Java 开始构建_rxjava_云O生-云原生)

Faunadb_第4张图片

最新的不一样,使用下面语法

Collection.create({
  name: 'todos'
})

5. 生成数据库秘钥

Faunadb_第5张图片

记住不要到account哪里去申请

Faunadb_第6张图片

6.springboot整合项目

依赖


com.faunadb
faunadb-java
4.4.0
compile

实体\service\controller均参考博文:使用 Spring Boot 使用 Fauna 和 Java 开始构建_rxjava_云O生-云原生

7.实体

参考这个也行:GitHub - fauna/faunadb-jvm: Scala and Java driver for FaunaDB v4

import lombok.Data;

@Data
public abstract class Entity {
    protected  String id;
}
import java.util.List;
import java.util.Optional;

public class Page  {

    private List data;
    private Optional before;
    private Optional after;


    public Page(List data, Optional before, Optional after) {
        this.data = data;
        this.before = before;
        this.after = after;
    }

    public List getData() {
        return data;
    }

    public void setData(List data) {
        this.data = data;
    }

    public Optional getBefore() {
        return before;
    }

    public void setBefore(Optional before) {
        this.before = before;
    }

    public Optional getAfter() {
        return after;
    }

    public void setAfter(Optional after) {
        this.after = after;
    }
}
package com.rulecheck.entity;

import java.util.Optional;

public class PaginationOptions {
    private Optional size;
    private Optional before;
    private Optional after;


    public PaginationOptions(Optional size, Optional before, Optional after) {
        this.size = size;
        this.before = before;
        this.after = after;
    }

    public Optional getSize() {
        return size;
    }

    public void setSize(Optional size) {
        this.size = size;
    }

    public Optional getBefore() {
        return before;
    }

    public void setBefore(Optional before) {
        this.before = before;
    }

    public Optional getAfter() {
        return after;
    }

    public void setAfter(Optional after) {
        this.after = after;
    }
}


import com.faunadb.client.types.FaunaConstructor;
import com.faunadb.client.types.FaunaField;

public class TodoEntity extends Entity {

    @FaunaField
    private String title;

    @FaunaField
    private String description;

    @FaunaConstructor
    public TodoEntity(@FaunaField("id") String id,
                      @FaunaField("title") String title,
                      @FaunaField("description") String description) {
        this.id = id;
        this.title = title;
        this.description = description;

    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getTitle() {
        return title;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }
}
package com.rulecheck.entity;

public class CreateOrUpdateTodoData {

    private String title;
    private String description;

    public CreateOrUpdateTodoData(String title, String description) {
        this.title = title;
        this.description = description;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }
}

8.service及接口

package com.rulecheck.service;

import com.faunadb.client.FaunaClient;
import com.faunadb.client.errors.NotFoundException;
import com.faunadb.client.query.Expr;
import com.faunadb.client.query.Pagination;
import com.faunadb.client.types.Value;
import com.rulecheck.entity.Entity;
import com.rulecheck.entity.Page;
import com.rulecheck.entity.PaginationOptions;
import jakarta.annotation.Resource;

import java.util.List;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.function.Function;
import java.util.stream.Collectors;

import static com.faunadb.client.query.Language.*;

import java.lang.Class;

public abstract class FaunaRepository implements Repository, IdentityFactory {

    @Resource
    private FaunaClient faunaClient;

    protected final Class entityType;
    protected final String collectionName;
    protected final String collectionIndexName;


    protected FaunaRepository(Class entityType, String collectionName, String collectionIndexName) {
        this.entityType = entityType;
        this.collectionName = collectionName;
        this.collectionIndexName = collectionIndexName;
    }

    // This method returns a unique valid Id leveraging Fauna's NewId function.
    @Override
    public CompletableFuture nextId() {

        CompletableFuture result =
                faunaClient.query(
                        NewId()
                )
                        .thenApply(value -> value.to(String.class).get());

        return result;
    }

    // This method saves an entity to the database using the saveQuery method below. It also returns the result of the saved entity.
    @Override
    public CompletableFuture save(T entity) {
        CompletableFuture result =
                faunaClient.query(
                        saveQuery(Value(entity.getId()), Value(entity))
                )
                        .thenApply(this::toEntity);

        return result;
    }

    // This method deletes from the data an entity(document) with the specified Id. 
    @Override
    public CompletableFuture> remove(String id) {
        CompletableFuture result =
                faunaClient.query(
                        Select(
                                Value("data"),
                                Delete(Ref(Collection(collectionName), Value(id)))
                        )
                )
                        .thenApply(this::toEntity);

        CompletableFuture> optionalResult = toOptionalResult(result);

        return optionalResult;
    }

    // This method finds an entity by its Id and returns the entity result.
    @Override
    public CompletableFuture> find(String id) {
        CompletableFuture result =
                faunaClient.query(
                        Select(
                                Value("data"),
                                Get(Ref(Collection(collectionName), Value(id)))
                        )
                )
                        .thenApply(this::toEntity);

        CompletableFuture> optionalResult = toOptionalResult(result);

        return optionalResult;
    }

    // This method returns all entities(documents) in the database collection using the paginationOptions parameters.
    @Override
    public CompletableFuture> findAll(PaginationOptions po) {
        Pagination paginationQuery = Paginate(Match(Index(Value(collectionIndexName))));
        po.getSize().ifPresent(size -> paginationQuery.size(size));
        po.getAfter().ifPresent(after -> paginationQuery.after(Ref(Collection(collectionName), Value(after))));
        po.getBefore().ifPresent(before -> paginationQuery.before(Ref(Collection(collectionName), Value(before))));

        CompletableFuture> result =
                faunaClient.query(
                        Map(
                                paginationQuery,
                                Lambda(Value("nextRef"), Select(Value("data"), Get(Var("nextRef"))))
                        )
                ).thenApply(this::toPage);

        return result;
    }


    // This is the saveQuery expression method used by the save method to persist the database.
    protected Expr saveQuery(Expr id, Expr data) {
        Expr query =
                Select(
                        Value("data"),
                        If(
                                Exists(Ref(Collection(collectionName), id)),
                                Replace(Ref(Collection(collectionName), id), Obj("data", data)),
                                Create(Ref(Collection(collectionName), id), Obj("data", data))
                        )
                );

        return query;
    }

    // This method converts a FaunaDB Value into an Entity.
    protected T toEntity(Value value) {
        return value.to(entityType).get();
    }

    // This method returns an optionalResult from a CompletableFuture result.
    protected CompletableFuture> toOptionalResult(CompletableFuture result) {
        CompletableFuture> optionalResult =
                result.handle((v, t) -> {
                    CompletableFuture> r = new CompletableFuture<>();
                    if(v != null) r.complete(Optional.of(v));
                    else if(t != null && t.getCause() instanceof NotFoundException) r.complete(Optional.empty());
                    else r.completeExceptionally(t);
                    return r;
                }).thenCompose(Function.identity());

        return optionalResult;
    }

    // This method converts a FaunaDB Value into a Page with the Entity type.
    protected Page toPage(Value value) {

        Optional after = value.at("after").asCollectionOf(Value.RefV.class).map(c -> c.iterator().next().getId()).getOptional();
        Optional before = value.at("before").asCollectionOf(Value.RefV.class).map(c -> c.iterator().next().getId()).getOptional();

        List data = value.at("data").collect(entityType).stream().collect(Collectors.toList());

        Page page = new Page(data, before, after);

        return page;
    }

}

import java.util.concurrent.CompletableFuture;

public interface IdentityFactory {

    CompletableFuture nextId();
}


import com.rulecheck.entity.Entity;
import com.rulecheck.entity.Page;
import com.rulecheck.entity.PaginationOptions;

import java.util.Optional;
import java.util.concurrent.CompletableFuture;

public interface Repository {

    // This method saves the given Entity into the Repository.
    CompletableFuture save(T entity);

    // This method finds an Entity for the given Id
    CompletableFuture> find(String id);

    // This method retrieves a Page of TodoEntity entities for the given PaginationOptions
    CompletableFuture> findAll(PaginationOptions po);

    // This method finds the Entity for the given Id and removes it. If no Entity can be found for the given Id an empty result is returned.
    CompletableFuture> remove(String id);
}
import com.rulecheck.entity.TodoEntity;
import org.springframework.stereotype.Repository;
@Repository
public class TodoRepository extends FaunaRepository {

    public TodoRepository(){
        super(TodoEntity.class, "todos", "all_todos");
    }

    //-- Custom repository operations specific to the TodoEntity will go below --//

}



import com.rulecheck.entity.CreateOrUpdateTodoData;
import com.rulecheck.entity.Page;
import com.rulecheck.entity.PaginationOptions;
import com.rulecheck.entity.TodoEntity;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Optional;
import java.util.concurrent.CompletableFuture;

@Service
public class TodoService {

    @Autowired
    private TodoRepository todoRepository;

    public CompletableFuture createTodo(CreateOrUpdateTodoData data) {
        CompletableFuture result =
                todoRepository.nextId()
                        .thenApply(id -> new TodoEntity(id, data.getTitle(), data.getDescription()))
                        .thenCompose(todoEntity -> todoRepository.save(todoEntity));

        return result;
    }

    public CompletableFuture> getTodo(String id) {
        return todoRepository.find(id);
    }

    public CompletableFuture> updateTodo(String id, CreateOrUpdateTodoData data) {
        CompletableFuture> result =
                todoRepository.find(id)
                        .thenCompose(optionalTodoEntity ->
                                optionalTodoEntity
                                        .map(todoEntity -> todoRepository.save(new TodoEntity(id, data.getTitle(), data.getDescription())).thenApply(Optional::of))
                                        .orElseGet(() -> CompletableFuture.completedFuture(Optional.empty())));

        return result;
    }

    public CompletableFuture> deleteTodo(String id) {
        return todoRepository.remove(id);
    }

    public CompletableFuture> getAllTodos(PaginationOptions po) {
        return todoRepository.findAll(po);
    }
}
import com.faunadb.client.FaunaClient;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Scope;


/**
 * description:
 */

@Slf4j
@SpringBootApplication
public class RuleCheckApplication {

    @Value("${fauna-db.secret}")
    private String serverKey;

    @Bean
    @Scope(value = ConfigurableBeanFactory.SCOPE_SINGLETON)
    public FaunaClient faunaConfiguration() {
        log.info("serverKey:{}", serverKey);
        FaunaClient faunaClient = FaunaClient.builder()
                .withSecret(serverKey)
                .build();

        return faunaClient;
    }

    public static void main(String[] args) {
        SpringApplication.run(RuleCheckApplication.class, args);
    }

}

9.属性文件配置属性

fauna-db.secret=fnAFN6K4SxAAQWm.........  自己生成数据库秘钥,非账户秘钥或者密码

Faunadb_第7张图片

10.controller

package com.rulecheck.controller;


import com.rulecheck.entity.CreateOrUpdateTodoData;
import com.rulecheck.entity.Page;
import com.rulecheck.entity.PaginationOptions;
import com.rulecheck.entity.TodoEntity;
import com.rulecheck.service.TodoService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.util.Optional;
import java.util.concurrent.CompletableFuture;

@RestController
public class TodoRestController {

    @Autowired
    private TodoService todoService;


    @PostMapping("/todos")
    public CompletableFuture createTodo(@RequestBody CreateOrUpdateTodoData data) {

        return todoService.createTodo(data)
                .thenApply(todoEntity -> new ResponseEntity(todoEntity, HttpStatus.CREATED));
    }


    @GetMapping("/todos/{id}")
    public CompletableFuture getTodo(@PathVariable("id") String id) {
        CompletableFuture result =
                todoService.getTodo(id)
                        .thenApply(optionalTodoEntity ->
                                optionalTodoEntity
                                        .map(todoEntity -> new ResponseEntity(todoEntity, HttpStatus.OK))
                                        .orElseGet(() -> new ResponseEntity(HttpStatus.NOT_FOUND))
                        );
        return result;
    }


    @PutMapping("/todos/{id}")
    public CompletableFuture updateTodo(@PathVariable("id") String id, @RequestBody CreateOrUpdateTodoData data) {
        CompletableFuture result =
                todoService.updateTodo(id, data)
                        .thenApply(optionalTodoEntity ->
                                optionalTodoEntity
                                        .map(todoEntity -> new ResponseEntity(todoEntity, HttpStatus.OK))
                                        .orElseGet(() -> new ResponseEntity(HttpStatus.NOT_FOUND)
                                        )
                        );
        return result;
    }

    @DeleteMapping(value = "/todos/{id}")
    public CompletableFuture deletePost(@PathVariable("id")String id) {
        CompletableFuture result =
                todoService.deleteTodo(id)
                        .thenApply(optionalTodoEntity ->
                                optionalTodoEntity
                                        .map(todo -> new ResponseEntity(todo, HttpStatus.OK))
                                        .orElseGet(() -> new ResponseEntity(HttpStatus.NOT_FOUND)
                                        )
                        );
        return result;
    }

    @GetMapping("/todos")
    public CompletableFuture> getAllTodos(
            @RequestParam("size") Optional size,
            @RequestParam("before") Optional before,
            @RequestParam("after") Optional after) {
        PaginationOptions po = new PaginationOptions(size, before, after);
        CompletableFuture> result = todoService.getAllTodos(po);
        return result;
    }
}

11. 参考pom依赖

    
        org.springframework.boot
        spring-boot-starter-parent
        3.1.3
        
    
    
        8
        8
        UTF-8
        3.5.3.1
        8.0.28
        2.11.0
    

    
        
            org.springframework.boot
            spring-boot-starter-web
        
        
            com.baomidou
            mybatis-plus-boot-starter
            ${mybatis-plus-boot-starter}
        
        
            mysql
            mysql-connector-java
           ${mysql-connector-java}
        

        
            com.baomidou
            mybatis-plus-generator
            ${mybatis-plus-boot-starter}
        
        
            org.springframework.boot
            spring-boot-starter-data-redis
        

        
            com.github.ben-manes.caffeine
            caffeine
        

        
            commons-io
            commons-io
            ${commons-io}
        

        
            org.projectlombok
            lombok
            1.18.28
            provided
        
        
            com.faunadb
            faunadb-java
            4.4.0
            compile
        
    

11.启动后postman试试

http://localhost:8080/todos

{

    "title":"create a job",

    "description":"this post request is todos"

}

Faunadb_第8张图片

你可能感兴趣的:(云数据库,数据库)