Site icon Vinsguru

Spring Boot CockroachDB Integration

Overview:

Applications have become very complex & user’s expectations have changed over the years! Applications nowadays have to be resilient and fault tolerant. It is easy to scale in / out our applications when they are designed stateless. But what about Database? Database is supposed to be a stateful application! How can we scale out horizontally?

CockroachDB is a prime example of NewSQL with ACID guarantee of SQL and the scale of NoSQL. It is open source and freely available for cloud-native and hybrid deployments.

CockroachDB:

CockroachDB’s architecture is more or less like Kafka. That is, it distributes the table across multiple nodes and maintains multiple replicas. When any of the node goes down, we can still read / write into the DB using other nodes. When the crashed node comes up, it gets synchronized with other nodes automatically!

Java applications can use the postgres driver to connect the CockroachDB.

Local Cluster:

We can use the below docker compose file to create a 3 node cluster.

version: "3"
services:
  roach1:
    image: cockroachdb/cockroach:v19.2.5
    container_name: roach1
    hostname: roach1
    volumes:
      - ./db/roach1:/cockroach/cockroach-data
    ports:
      - 9090:8080
      - 26257:26257    
    command: ["start", "--insecure", "--advertise-addr=roach1"]
  roach2:
    image: cockroachdb/cockroach:v19.2.5
    container_name: roach2
    hostname: roach2
    volumes:
      - ./db/roach2:/cockroach/cockroach-data
    ports:
      - 9091:8080
      - 26258:26257    
    command: ["start", "--insecure", "--advertise-addr=roach2", "--join=roach1"]
  roach3:
    image: cockroachdb/cockroach:v19.2.5
    container_name: roach3
    hostname: roach3
    volumes:
      - ./db/roach3:/cockroach/cockroach-data
    ports:
      - 9092:8080
      - 26259:26257    
    command: ["start", "--insecure", "--advertise-addr=roach3", "--join=roach1"]
docker-compose up
docker exec -it roach1 ./cockroach sql --insecure
create database vinsguru;
create user vins;
grant all on database vinsguru to vins;

Admin UI:

CREATE TABLE product(
   id VARCHAR (50) PRIMARY KEY,
   description VARCHAR (500),
   price numeric (10,2) NOT NULL
);

 

 

Spring Boot Integration:

@Data
@Entity
@ToString
public class Product {

    @Id
    private UUID id;
    private String description;
    private double price;

}
@Repository
public interface ProductRepository extends JpaRepository<Product, UUID> {
}
@Service
public class ProductService {

    @Autowired
    private ProductRepository productRepository;

    // insert
    public void createProduct(Product product){
        UUID uuid = UUID.randomUUID();
        product.setId(uuid);
        this.productRepository.save(product);
    }

    // select all
    public List<Product> getAllProducts(){
        return this.productRepository.findAll();
    }

    // delete
    @Transactional
    public void deleteProduct(UUID id){
        this.productRepository
                .findById(id)
                .ifPresent(this.productRepository::delete);
    }

    // update
    @Transactional
    public Product updateProduct(Product product){
        return this.productRepository
               .save(product);
    }

}
@RestController
@RequestMapping("product")
public class ProductController {

    @Autowired
    private ProductService productService;

    @PostMapping("/create")
    public void createProduct(@RequestBody Product product){
        this.productService.createProduct(product);
    }

    @GetMapping("/all")
    public Mono<List<Product>> getAllProducts(){
        return Mono.fromSupplier(() -> this.productService.getAllProducts());
    }

    @DeleteMapping("/delete/{id}")
    public void deleteProduct(@PathVariable final String id){
        this.productService.deleteProduct(UUID.fromString(id));
    }

    @PutMapping("/update")
    public Product updateProduct(@RequestBody final Product product){
       return this.productService.updateProduct(product);
    }

}
server:
  port: 8080
spring:
  datasource:
    url: jdbc:postgresql://localhost:26258/vinsguru
    username: vins
    password:

Fault Tolerance & Recovery:

 

All the source code is available here.

 

Happy coding 🙂

 

Share This:

Exit mobile version