Thursday, November 18, 2021

Spring Boot 2 Spring Data Kotlin Cassandra CRUD

we're integration Spring Boot Kotlin Cassandra  CRUD.

  • Configuration Spring boot, Spring Data, Kotlin with Cassandra Database.
  • Define Data's Models, Repository and Services.
  • Spring Rest Controllers  

Spring Boot Kotlin Cassandra Rest CRUD API 

These are APIs that we need to provide:

MethodsUrls
POST /services/ws/save
GET /services/ws/users
PUT /services/ws/update/:email
DELETE /services/ws/delete/:email

Technology

  • Kotlin 1.5.31
  • Java 11
  • Spring Boot 2.5.6
  • Cassandra 4.0.1
  • Cqlsh 6.0.0
  • Maven 3.6.3
  • IntelliJ IDEA 2021.2.3 
  • Docker

Project Structure






















Configuration Spring Boot kotlin Cassandra project 

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.6</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.henry</groupId>
<artifactId>SpringBootCassandraKotlin</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>SpringBootCassandraKotlin</name>
<description>Crud Cassandra with kotlin</description>
<properties>
<java.version>11</java.version>
<kotlin.version>1.5.31</kotlin.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-cassandra</artifactId>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-reflect</artifactId>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib-jdk8</artifactId>
</dependency>

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

</dependencies>

<build>
<sourceDirectory>${project.basedir}/src/main/kotlin</sourceDirectory>
<testSourceDirectory>${project.basedir}/src/test/kotlin</testSourceDirectory>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-maven-plugin</artifactId>
<configuration>
<args>
<arg>-Xjsr305=strict</arg>
</args>
<compilerPlugins>
<plugin>spring</plugin>
</compilerPlugins>
</configuration>
<dependencies>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-maven-allopen</artifactId>
<version>${kotlin.version}</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>

</project>

application.yml

server:
servlet:
context-path: /services
port: 9000

spring:
data:
cassandra:
keyspace-name: test_keyspace
contact-points: localhost:9042
local-datacenter: datacenter1


Set up Cassandra by Docker


docker pull cassandra

 docker run --name cassandra -p 127.0.0.1:9042:9042 -p 127.0.0.1:9160:9160   -d cassandra

 docker exec -it cassandra /bin/bash

 #cqlsh






Check datacenter name:

cqlsh> use system;
cqlsh:system> select data_center from local;

 data_center
-------------
 datacenter1

(1 rows)
cqlsh:system>

 
We Created keyspaces: test_keyspace.

create keyspace test_keyspace with replication={'class':'SimpleStrategy', 'replication_factor':1};

use test_keyspace;

create table users
(
    email varchar primary key,
    name varchar,
    age int
);


Data class model

package com.henry.model

import org.springframework.data.cassandra.core.mapping.PrimaryKey
import org.springframework.data.cassandra.core.mapping.Table

@Table
data class Users(@PrimaryKey
var email: String, var name: String, var age: Int)


Repository Interface

package com.henry.repository

import com.henry.model.Users
import org.springframework.data.cassandra.repository.CassandraRepository

interface UserRepository : CassandraRepository<Users,String> {
fun findByNameContaining(name: String?): List<Users?>?

}

Service Interface

package com.henry.services

import com.henry.model.Users

interface UserService {
fun byContName(name: String): List<Users?>?
fun findAllUsers(): MutableList<Users>;
fun saveUser(user: Users): Users
fun updateUser(email: String, user: Users): Users
fun deleteUser(email: String)
}

Service Class

package com.henry.services.impl

import com.henry.model.Users
import com.henry.repository.UserRepository
import com.henry.services.UserService
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.stereotype.Service
import java.util.*

@Service
class UserServiceImpl : UserService {

@Autowired
lateinit var userRepository: UserRepository;

override fun byContName(name: String): List<Users?>? {
return userRepository.findByNameContaining(name)
}

override fun findAllUsers(): MutableList<Users> {
return userRepository.findAll()
}

override fun saveUser(user: Users): Users {
return userRepository.save(user)
}

override fun updateUser(email: String, user: Users): Users {
val obj: Optional<Users> = userRepository.findById(email)
obj.get().age = user.age
obj.get().name = user.name
return userRepository.save(obj.get())

}

override fun deleteUser(email: String) {
userRepository.deleteById(email)
}
}

Spring Rest APIs Controller

package com.henry.controller

import com.henry.model.Users
import com.henry.services.UserService
import org.springframework.http.HttpStatus
import org.springframework.http.ResponseEntity
import org.springframework.web.bind.annotation.*


@CrossOrigin(origins = ["http://localhost:9000"])
@RestController
@RequestMapping("/ws")
class UserController(private val userService: UserService) {

@GetMapping("/users")
fun getAllUsers(): ResponseEntity<MutableList<Users>>? {
return ResponseEntity(userService.findAllUsers(), HttpStatus.OK)
}

@PostMapping("/save")
fun save(@RequestBody user: Users): ResponseEntity<Users>?{
return ResponseEntity(userService.saveUser(user), HttpStatus.OK)
}

@PutMapping("/update/{email:.*}")
fun update(@PathVariable email: String, @RequestBody user: Users): ResponseEntity<Users>?{
return ResponseEntity(userService.updateUser(email, user), HttpStatus.OK)
}

@DeleteMapping("/delete/{email:.*}")
fun delete(@PathVariable email: String): ResponseEntity<Unit> {
return ResponseEntity(userService.deleteUser(email), HttpStatus.OK)
}




}

Run & Test

Run Spring Boot application with command: mvn spring-boot:run. by console, IntelliJ etc.

POST.








































GET.



































PUT.























DELETE.




















Source Code

Here on Github.


References.

https://www.bezkoder.com/spring-boot-cassandra-crud/
https://www.youtube.com/channel/UCHRnRlWQuZYDmnuB7SbXIpQ





Monday, November 15, 2021

Apache Cassandra with Ubuntu 20.04

Apache Cassandra with docker.

1.     Installed from docker 

    $    docker pull cassandra:latest

    $   docker run --name you_cass_cluster cassandra:latest

    $   docker ps


    

$   docker exec -it you_cass_cluster cqlsh

    



    

2.    Supported Data Types.

Supported Data Types
CQL TypeDescription
asciiUS-ASCII character string
bigint64-bit signed long
blobArbitrary bytes (no validation), expressed as hexadecimal
booleantrue or false
counterDistributed counter value (64-bit long)
decimalVariable-precision decimal
double64-bit IEEE-754 floating point
float32-bit IEEE-754 floating point
int32-bit signed integer
textUTF-8 encoded string
timestampDate plus time, encoded as 8 bytes since epoch
uuidType 1 or type 4 UUID
timeuuidType 1 UUID only (CQL3)
varcharUTF-8 encoded string
varintArbitrary-precision integer


3.    Created on KEYSPACES with next command.

        CREATE KEYSPACE test_kesypace WITH replication = {'class': 'SimpleStrategy', 'replication_factor': '1'} AND durable_writes = 'true';

4.     Created Tables 

    use test_kesypace;

    CREATE TABLE employee_by_id

  (
     id       INT PRIMARY KEY,
     name     TEXT,
     position TEXT
  ); 

CREATE TABLE employee_by_car_make
  (
     car_make  TEXT,
     id        INT,
     car_model TEXT,
     PRIMARY KEY(car_make, id)

  );    

CREATE TABLE employee_by_car_make_sorted
  (
     car_make TEXT,
     age      INT,
     id       INT,
     name     TEXT,
     PRIMARY KEY(car_make, age, id)
  ); 

CREATE TABLE employee_by_car_make_and_model
             (
                          car_make TEXT,
                          car_model TEXT,
                          id INT,
                          name TEXT,
                          PRIMARY KEY((car_make, car_model), id)
             );

5.     Insert and update

INSERT INTO employee_by_id
            (id,
             name,
             position)
VALUES      ( 1,
             'Henry',
             'Developer'); 


UPDATE employee_by_car_make
using  ttl 60
SET    car_model = 'Truck'
WHERE  car_make ='TOYOTA'
AND    id = 1;

6. SELECT 

Cassandra DB just search by id.

SELECT *
FROM   employee_by_id
WHERE  id = 1; 


            






References:

https://www.youtube.com/channel/UCHRnRlWQuZYDmnuB7SbXIpQ



        


Sunday, September 5, 2021

Return table on function + object types + Oracle

Sometimes we need to function on oracle, return of table because propably you need to send dinamic parameters of query, you can resolve the problem with materialized view or view but both your parameters is define, then when you want change the params you can replace or create again. but with objetc types not is necessary.


I suggest you, to read to concept object types. because i only share the example but not concept.


Step 1. i create my real or exist table and insert. for this example.

CREATE TABLE my_real_table
  (
     username VARCHAR2(25),
     age      NUMBER
  ); 


INSERT ALL
INTO my_real_table (username, ageVALUES ('User1', 25)
INTO my_real_table (username, ageVALUES ('User2', 25)
INTO my_real_table (username, ageVALUES ('User3', 33)
INTO my_real_table (username, ageVALUES ('User4', 30)
INTO my_real_table (username, ageVALUES ('User5', 40)
SELECT *
FROM   dual; 

Step 2.

Create a object of your table.

CREATE OR replace TYPE obj_test AS object (
  username VARCHAR2(25),
  age      NUMBER ); 


Step 3.

Create a type of your object.

CREATE OR replace TYPE t_test
  AS TABLE OF OBJ_TEST; 


Step 4. Create of function with parameters and return the table depends on parameters.


CREATE OR replace FUNCTION Fu_test (v_age IN NUMBER)
RETURN T_TEST
IS
  return_value T_TEST;
BEGIN
    SELECT Obj_test(username, age)
    bulk   collect INTO return_value
    FROM   (SELECT username,
                   age
            FROM   my_real_table
            WHERE  age > = v_age);

    RETURN return_value;
END; 

Step 4. you can send diferent parameters the function and return table. 

SELECT *
FROM   TABLE(Fu_test(30)); 











That it is.




🚀 Spring Boot 3.5 → 4.0.3 Migration Summary

Import Changes, API Adjustments & Compatibility Results Migration summary from Spring Boot 3.5 → 4.0, including breaking changes, depend...