• Faunadb


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

    本文使用java语言,其他语言可以跳过;有想直接使用的可以参考(无法访问外网,可以搞个vpn吧!!!,有时会遇到网络问题):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

    2.了解一下FQL

    建议按照图看下去

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

    最好是跟着官网文档走

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

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

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

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

    5. 生成数据库秘钥

    记住不要到account哪里去申请

    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

    1. import lombok.Data;
    2. @Data
    3. public abstract class Entity {
    4. protected String id;
    5. }
    1. import java.util.List;
    2. import java.util.Optional;
    3. public class Page {
    4. private List data;
    5. private Optional before;
    6. private Optional after;
    7. public Page(List data, Optional before, Optional after) {
    8. this.data = data;
    9. this.before = before;
    10. this.after = after;
    11. }
    12. public List getData() {
    13. return data;
    14. }
    15. public void setData(List data) {
    16. this.data = data;
    17. }
    18. public Optional getBefore() {
    19. return before;
    20. }
    21. public void setBefore(Optional before) {
    22. this.before = before;
    23. }
    24. public Optional getAfter() {
    25. return after;
    26. }
    27. public void setAfter(Optional after) {
    28. this.after = after;
    29. }
    30. }
    1. package com.rulecheck.entity;
    2. import java.util.Optional;
    3. public class PaginationOptions {
    4. private Optional size;
    5. private Optional before;
    6. private Optional after;
    7. public PaginationOptions(Optional size, Optional before, Optional after) {
    8. this.size = size;
    9. this.before = before;
    10. this.after = after;
    11. }
    12. public Optional getSize() {
    13. return size;
    14. }
    15. public void setSize(Optional size) {
    16. this.size = size;
    17. }
    18. public Optional getBefore() {
    19. return before;
    20. }
    21. public void setBefore(Optional before) {
    22. this.before = before;
    23. }
    24. public Optional getAfter() {
    25. return after;
    26. }
    27. public void setAfter(Optional after) {
    28. this.after = after;
    29. }
    30. }
    1. import com.faunadb.client.types.FaunaConstructor;
    2. import com.faunadb.client.types.FaunaField;
    3. public class TodoEntity extends Entity {
    4. @FaunaField
    5. private String title;
    6. @FaunaField
    7. private String description;
    8. @FaunaConstructor
    9. public TodoEntity(@FaunaField("id") String id,
    10. @FaunaField("title") String title,
    11. @FaunaField("description") String description) {
    12. this.id = id;
    13. this.title = title;
    14. this.description = description;
    15. }
    16. public void setTitle(String title) {
    17. this.title = title;
    18. }
    19. public String getTitle() {
    20. return title;
    21. }
    22. public String getDescription() {
    23. return description;
    24. }
    25. public void setDescription(String description) {
    26. this.description = description;
    27. }
    28. }
    1. package com.rulecheck.entity;
    2. public class CreateOrUpdateTodoData {
    3. private String title;
    4. private String description;
    5. public CreateOrUpdateTodoData(String title, String description) {
    6. this.title = title;
    7. this.description = description;
    8. }
    9. public String getTitle() {
    10. return title;
    11. }
    12. public void setTitle(String title) {
    13. this.title = title;
    14. }
    15. public String getDescription() {
    16. return description;
    17. }
    18. public void setDescription(String description) {
    19. this.description = description;
    20. }
    21. }

    8.service及接口

    1. package com.rulecheck.service;
    2. import com.faunadb.client.FaunaClient;
    3. import com.faunadb.client.errors.NotFoundException;
    4. import com.faunadb.client.query.Expr;
    5. import com.faunadb.client.query.Pagination;
    6. import com.faunadb.client.types.Value;
    7. import com.rulecheck.entity.Entity;
    8. import com.rulecheck.entity.Page;
    9. import com.rulecheck.entity.PaginationOptions;
    10. import jakarta.annotation.Resource;
    11. import java.util.List;
    12. import java.util.Optional;
    13. import java.util.concurrent.CompletableFuture;
    14. import java.util.function.Function;
    15. import java.util.stream.Collectors;
    16. import static com.faunadb.client.query.Language.*;
    17. import java.lang.Class;
    18. public abstract class FaunaRepositoryextends Entity > implements Repository, IdentityFactory {
    19. @Resource
    20. private FaunaClient faunaClient;
    21. protected final Class entityType;
    22. protected final String collectionName;
    23. protected final String collectionIndexName;
    24. protected FaunaRepository(Class entityType, String collectionName, String collectionIndexName) {
    25. this.entityType = entityType;
    26. this.collectionName = collectionName;
    27. this.collectionIndexName = collectionIndexName;
    28. }
    29. // This method returns a unique valid Id leveraging Fauna's NewId function.
    30. @Override
    31. public CompletableFuture nextId() {
    32. CompletableFuture result =
    33. faunaClient.query(
    34. NewId()
    35. )
    36. .thenApply(value -> value.to(String.class).get());
    37. return result;
    38. }
    39. // This method saves an entity to the database using the saveQuery method below. It also returns the result of the saved entity.
    40. @Override
    41. public CompletableFuture save(T entity) {
    42. CompletableFuture result =
    43. faunaClient.query(
    44. saveQuery(Value(entity.getId()), Value(entity))
    45. )
    46. .thenApply(this::toEntity);
    47. return result;
    48. }
    49. // This method deletes from the data an entity(document) with the specified Id.
    50. @Override
    51. public CompletableFuture> remove(String id) {
    52. CompletableFuture result =
    53. faunaClient.query(
    54. Select(
    55. Value("data"),
    56. Delete(Ref(Collection(collectionName), Value(id)))
    57. )
    58. )
    59. .thenApply(this::toEntity);
    60. CompletableFuture> optionalResult = toOptionalResult(result);
    61. return optionalResult;
    62. }
    63. // This method finds an entity by its Id and returns the entity result.
    64. @Override
    65. public CompletableFuture> find(String id) {
    66. CompletableFuture result =
    67. faunaClient.query(
    68. Select(
    69. Value("data"),
    70. Get(Ref(Collection(collectionName), Value(id)))
    71. )
    72. )
    73. .thenApply(this::toEntity);
    74. CompletableFuture> optionalResult = toOptionalResult(result);
    75. return optionalResult;
    76. }
    77. // This method returns all entities(documents) in the database collection using the paginationOptions parameters.
    78. @Override
    79. public CompletableFuture> findAll(PaginationOptions po) {
    80. Pagination paginationQuery = Paginate(Match(Index(Value(collectionIndexName))));
    81. po.getSize().ifPresent(size -> paginationQuery.size(size));
    82. po.getAfter().ifPresent(after -> paginationQuery.after(Ref(Collection(collectionName), Value(after))));
    83. po.getBefore().ifPresent(before -> paginationQuery.before(Ref(Collection(collectionName), Value(before))));
    84. CompletableFuture> result =
    85. faunaClient.query(
    86. Map(
    87. paginationQuery,
    88. Lambda(Value("nextRef"), Select(Value("data"), Get(Var("nextRef"))))
    89. )
    90. ).thenApply(this::toPage);
    91. return result;
    92. }
    93. // This is the saveQuery expression method used by the save method to persist the database.
    94. protected Expr saveQuery(Expr id, Expr data) {
    95. Expr query =
    96. Select(
    97. Value("data"),
    98. If(
    99. Exists(Ref(Collection(collectionName), id)),
    100. Replace(Ref(Collection(collectionName), id), Obj("data", data)),
    101. Create(Ref(Collection(collectionName), id), Obj("data", data))
    102. )
    103. );
    104. return query;
    105. }
    106. // This method converts a FaunaDB Value into an Entity.
    107. protected T toEntity(Value value) {
    108. return value.to(entityType).get();
    109. }
    110. // This method returns an optionalResult from a CompletableFuture result.
    111. protected CompletableFuture> toOptionalResult(CompletableFuture result) {
    112. CompletableFuture> optionalResult =
    113. result.handle((v, t) -> {
    114. CompletableFuture> r = new CompletableFuture<>();
    115. if(v != null) r.complete(Optional.of(v));
    116. else if(t != null && t.getCause() instanceof NotFoundException) r.complete(Optional.empty());
    117. else r.completeExceptionally(t);
    118. return r;
    119. }).thenCompose(Function.identity());
    120. return optionalResult;
    121. }
    122. // This method converts a FaunaDB Value into a Page with the Entity type.
    123. protected Page toPage(Value value) {
    124. Optional after = value.at("after").asCollectionOf(Value.RefV.class).map(c -> c.iterator().next().getId()).getOptional();
    125. Optional before = value.at("before").asCollectionOf(Value.RefV.class).map(c -> c.iterator().next().getId()).getOptional();
    126. List data = value.at("data").collect(entityType).stream().collect(Collectors.toList());
    127. Page page = new Page(data, before, after);
    128. return page;
    129. }
    130. }

    1. import java.util.concurrent.CompletableFuture;
    2. public interface IdentityFactory {
    3. CompletableFuture nextId();
    4. }
    1. import com.rulecheck.entity.Entity;
    2. import com.rulecheck.entity.Page;
    3. import com.rulecheck.entity.PaginationOptions;
    4. import java.util.Optional;
    5. import java.util.concurrent.CompletableFuture;
    6. public interface Repositoryextends Entity> {
    7. // This method saves the given Entity into the Repository.
    8. CompletableFuture save(T entity);
    9. // This method finds an Entity for the given Id
    10. CompletableFuture> find(String id);
    11. // This method retrieves a Page of TodoEntity entities for the given PaginationOptions
    12. CompletableFuture> findAll(PaginationOptions po);
    13. // 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.
    14. CompletableFuture> remove(String id);
    15. }
    1. import com.rulecheck.entity.TodoEntity;
    2. import org.springframework.stereotype.Repository;
    3. @Repository
    4. public class TodoRepository extends FaunaRepository {
    5. public TodoRepository(){
    6. super(TodoEntity.class, "todos", "all_todos");
    7. }
    8. //-- Custom repository operations specific to the TodoEntity will go below --//
    9. }

    1. import com.rulecheck.entity.CreateOrUpdateTodoData;
    2. import com.rulecheck.entity.Page;
    3. import com.rulecheck.entity.PaginationOptions;
    4. import com.rulecheck.entity.TodoEntity;
    5. import org.springframework.beans.factory.annotation.Autowired;
    6. import org.springframework.stereotype.Service;
    7. import java.util.Optional;
    8. import java.util.concurrent.CompletableFuture;
    9. @Service
    10. public class TodoService {
    11. @Autowired
    12. private TodoRepository todoRepository;
    13. public CompletableFuture createTodo(CreateOrUpdateTodoData data) {
    14. CompletableFuture result =
    15. todoRepository.nextId()
    16. .thenApply(id -> new TodoEntity(id, data.getTitle(), data.getDescription()))
    17. .thenCompose(todoEntity -> todoRepository.save(todoEntity));
    18. return result;
    19. }
    20. public CompletableFuture> getTodo(String id) {
    21. return todoRepository.find(id);
    22. }
    23. public CompletableFuture> updateTodo(String id, CreateOrUpdateTodoData data) {
    24. CompletableFuture> result =
    25. todoRepository.find(id)
    26. .thenCompose(optionalTodoEntity ->
    27. optionalTodoEntity
    28. .map(todoEntity -> todoRepository.save(new TodoEntity(id, data.getTitle(), data.getDescription())).thenApply(Optional::of))
    29. .orElseGet(() -> CompletableFuture.completedFuture(Optional.empty())));
    30. return result;
    31. }
    32. public CompletableFuture> deleteTodo(String id) {
    33. return todoRepository.remove(id);
    34. }
    35. public CompletableFuture> getAllTodos(PaginationOptions po) {
    36. return todoRepository.findAll(po);
    37. }
    38. }
    1. import com.faunadb.client.FaunaClient;
    2. import lombok.extern.slf4j.Slf4j;
    3. import org.springframework.beans.factory.annotation.Value;
    4. import org.springframework.beans.factory.config.ConfigurableBeanFactory;
    5. import org.springframework.boot.SpringApplication;
    6. import org.springframework.boot.autoconfigure.SpringBootApplication;
    7. import org.springframework.context.annotation.Bean;
    8. import org.springframework.context.annotation.Scope;
    9. /**
    10. * description:
    11. */
    12. @Slf4j
    13. @SpringBootApplication
    14. public class RuleCheckApplication {
    15. @Value("${fauna-db.secret}")
    16. private String serverKey;
    17. @Bean
    18. @Scope(value = ConfigurableBeanFactory.SCOPE_SINGLETON)
    19. public FaunaClient faunaConfiguration() {
    20. log.info("serverKey:{}", serverKey);
    21. FaunaClient faunaClient = FaunaClient.builder()
    22. .withSecret(serverKey)
    23. .build();
    24. return faunaClient;
    25. }
    26. public static void main(String[] args) {
    27. SpringApplication.run(RuleCheckApplication.class, args);
    28. }
    29. }

    9.属性文件配置属性

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

    10.controller

    1. package com.rulecheck.controller;
    2. import com.rulecheck.entity.CreateOrUpdateTodoData;
    3. import com.rulecheck.entity.Page;
    4. import com.rulecheck.entity.PaginationOptions;
    5. import com.rulecheck.entity.TodoEntity;
    6. import com.rulecheck.service.TodoService;
    7. import org.springframework.beans.factory.annotation.Autowired;
    8. import org.springframework.http.HttpStatus;
    9. import org.springframework.http.ResponseEntity;
    10. import org.springframework.web.bind.annotation.*;
    11. import java.util.Optional;
    12. import java.util.concurrent.CompletableFuture;
    13. @RestController
    14. public class TodoRestController {
    15. @Autowired
    16. private TodoService todoService;
    17. @PostMapping("/todos")
    18. public CompletableFuture createTodo(@RequestBody CreateOrUpdateTodoData data) {
    19. return todoService.createTodo(data)
    20. .thenApply(todoEntity -> new ResponseEntity(todoEntity, HttpStatus.CREATED));
    21. }
    22. @GetMapping("/todos/{id}")
    23. public CompletableFuture getTodo(@PathVariable("id") String id) {
    24. CompletableFuture result =
    25. todoService.getTodo(id)
    26. .thenApply(optionalTodoEntity ->
    27. optionalTodoEntity
    28. .map(todoEntity -> new ResponseEntity(todoEntity, HttpStatus.OK))
    29. .orElseGet(() -> new ResponseEntity(HttpStatus.NOT_FOUND))
    30. );
    31. return result;
    32. }
    33. @PutMapping("/todos/{id}")
    34. public CompletableFuture updateTodo(@PathVariable("id") String id, @RequestBody CreateOrUpdateTodoData data) {
    35. CompletableFuture result =
    36. todoService.updateTodo(id, data)
    37. .thenApply(optionalTodoEntity ->
    38. optionalTodoEntity
    39. .map(todoEntity -> new ResponseEntity(todoEntity, HttpStatus.OK))
    40. .orElseGet(() -> new ResponseEntity(HttpStatus.NOT_FOUND)
    41. )
    42. );
    43. return result;
    44. }
    45. @DeleteMapping(value = "/todos/{id}")
    46. public CompletableFuture deletePost(@PathVariable("id")String id) {
    47. CompletableFuture result =
    48. todoService.deleteTodo(id)
    49. .thenApply(optionalTodoEntity ->
    50. optionalTodoEntity
    51. .map(todo -> new ResponseEntity(todo, HttpStatus.OK))
    52. .orElseGet(() -> new ResponseEntity(HttpStatus.NOT_FOUND)
    53. )
    54. );
    55. return result;
    56. }
    57. @GetMapping("/todos")
    58. public CompletableFuture> getAllTodos(
    59. @RequestParam("size") Optional size,
    60. @RequestParam("before") Optional before,
    61. @RequestParam("after") Optional after) {
    62. PaginationOptions po = new PaginationOptions(size, before, after);
    63. CompletableFuture> result = todoService.getAllTodos(po);
    64. return result;
    65. }
    66. }

    11. 参考pom依赖

    1. <parent>
    2. <groupId>org.springframework.bootgroupId>
    3. <artifactId>spring-boot-starter-parentartifactId>
    4. <version>3.1.3version>
    5. <relativePath>relativePath>
    6. parent>
    7. <properties>
    8. <maven.compiler.source>8maven.compiler.source>
    9. <maven.compiler.target>8maven.compiler.target>
    10. <project.build.sourceEncoding>UTF-8project.build.sourceEncoding>
    11. <mybatis-plus-boot-starter>3.5.3.1mybatis-plus-boot-starter>
    12. <mysql-connector-java>8.0.28mysql-connector-java>
    13. <commons-io>2.11.0commons-io>
    14. properties>
    15. <dependencies>
    16. <dependency>
    17. <groupId>org.springframework.bootgroupId>
    18. <artifactId>spring-boot-starter-webartifactId>
    19. dependency>
    20. <dependency>
    21. <groupId>com.baomidougroupId>
    22. <artifactId>mybatis-plus-boot-starterartifactId>
    23. <version>${mybatis-plus-boot-starter}version>
    24. dependency>
    25. <dependency>
    26. <groupId>mysqlgroupId>
    27. <artifactId>mysql-connector-javaartifactId>
    28. <version>${mysql-connector-java}version>
    29. dependency>
    30. <dependency>
    31. <groupId>com.baomidougroupId>
    32. <artifactId>mybatis-plus-generatorartifactId>
    33. <version>${mybatis-plus-boot-starter}version>
    34. dependency>
    35. <dependency>
    36. <groupId>org.springframework.bootgroupId>
    37. <artifactId>spring-boot-starter-data-redisartifactId>
    38. dependency>
    39. <dependency>
    40. <groupId>com.github.ben-manes.caffeinegroupId>
    41. <artifactId>caffeineartifactId>
    42. dependency>
    43. <dependency>
    44. <groupId>commons-iogroupId>
    45. <artifactId>commons-ioartifactId>
    46. <version>${commons-io}version>
    47. dependency>
    48. <dependency>
    49. <groupId>org.projectlombokgroupId>
    50. <artifactId>lombokartifactId>
    51. <version>1.18.28version>
    52. <scope>providedscope>
    53. dependency>
    54. <dependency>
    55. <groupId>com.faunadbgroupId>
    56. <artifactId>faunadb-javaartifactId>
    57. <version>4.4.0version>
    58. <scope>compilescope>
    59. dependency>
    60. dependencies>

    11.启动后postman试试

    http://localhost:8080/todos

    {

        "title":"create a job",

        "description":"this post request is todos"

    }

  • 相关阅读:
    【三十】springboot项目上高并发解决示例
    [附源码]计算机毕业设计学生综合数据分析系统Springboot程序
    网络安全(黑客)自学
    WinCC趋势跨度设置(时间范围)
    MATLAB图像处理介绍
    [Spring] Spring5——IOC 简介(二)
    IDEA 集成 Github(八)——Git
    Python编程语言学习:shap.force_plot函数的源码解读之详细攻略
    导包问题解决--ImportError: DLL load failed while importing _path: 找不到指定的模块
    iNFTnews|NFT和艺术有何区别?
  • 原文地址:https://blog.csdn.net/haohaounique/article/details/132913153