Faunadb和google spanner都属于云分布式数据库天然支持分片(无需做分表分库操作,一库搞定,当然价格另说),国内的也有比如TiDB Oceanbase等
本文使用java语言,其他语言可以跳过;有想直接使用的可以参考(无法访问外网,可以搞个vpn吧!!!,有时会遇到网络问题):GitHub - fauna/faunadb-jvm: Scala and Java driver for FaunaDB v4
此文旨在想了解的小伙伴看看(免费使用30天)
本文演示使用的jdk版本为jdk21
目录
4.点击搜索框中的dashbord进入到控制台然后到控制台创建集合
使用github账号或者注册一个
Welcome to Fauna docs - Fauna Documentation

建议按照图看下去

最好是跟着官网文档走

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

最新的不一样,使用下面语法
Collection.create({
name: 'todos'
})

记住不要到account哪里去申请

依赖
实体\service\controller均参考博文:使用 Spring Boot 使用 Fauna 和 Java 开始构建_rxjava_云O生-云原生
参考这个也行: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;
- }
- }
- 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
extends Entity > 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
extends Entity> { -
- // 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);
- }
-
- }
fauna-db.secret=fnAFN6K4SxAAQWm......... 自己生成数据库秘钥,非账户秘钥或者密码

- 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依赖
- <parent>
- <groupId>org.springframework.bootgroupId>
- <artifactId>spring-boot-starter-parentartifactId>
- <version>3.1.3version>
- <relativePath>relativePath>
- parent>
- <properties>
- <maven.compiler.source>8maven.compiler.source>
- <maven.compiler.target>8maven.compiler.target>
- <project.build.sourceEncoding>UTF-8project.build.sourceEncoding>
- <mybatis-plus-boot-starter>3.5.3.1mybatis-plus-boot-starter>
- <mysql-connector-java>8.0.28mysql-connector-java>
- <commons-io>2.11.0commons-io>
- properties>
- <dependencies>
- <dependency>
- <groupId>org.springframework.bootgroupId>
- <artifactId>spring-boot-starter-webartifactId>
- dependency>
- <dependency>
- <groupId>com.baomidougroupId>
- <artifactId>mybatis-plus-boot-starterartifactId>
- <version>${mybatis-plus-boot-starter}version>
- dependency>
- <dependency>
- <groupId>mysqlgroupId>
- <artifactId>mysql-connector-javaartifactId>
- <version>${mysql-connector-java}version>
- dependency>
-
- <dependency>
- <groupId>com.baomidougroupId>
- <artifactId>mybatis-plus-generatorartifactId>
- <version>${mybatis-plus-boot-starter}version>
- dependency>
- <dependency>
- <groupId>org.springframework.bootgroupId>
- <artifactId>spring-boot-starter-data-redisartifactId>
- dependency>
-
- <dependency>
- <groupId>com.github.ben-manes.caffeinegroupId>
- <artifactId>caffeineartifactId>
- dependency>
-
- <dependency>
- <groupId>commons-iogroupId>
- <artifactId>commons-ioartifactId>
- <version>${commons-io}version>
- dependency>
-
- <dependency>
- <groupId>org.projectlombokgroupId>
- <artifactId>lombokartifactId>
- <version>1.18.28version>
- <scope>providedscope>
- dependency>
- <dependency>
- <groupId>com.faunadbgroupId>
- <artifactId>faunadb-javaartifactId>
- <version>4.4.0version>
- <scope>compilescope>
- dependency>
- dependencies>
{
"title":"create a job",
"description":"this post request is todos"
}
