BAEL-4971 - Object mapping with Cassandra (#13427)

* BAEL-4971 - Object mapping with Cassandra

* BAEL-4971 - Object mapping with Cassandra

* BAEL-4971 - Object mapping with Cassandra - changing test name

* BAEL-4971 - Object mapping with Cassandra - code formatting

* BAEL-4971 - Object mapping with Cassandra - review incorporation
This commit is contained in:
Abhinav Pandey 2023-02-20 13:52:52 +05:30 committed by GitHub
parent 8f2e92dacb
commit 639de9687e
10 changed files with 356 additions and 0 deletions

View File

@ -60,8 +60,32 @@
<version>${system.stubs.version}</version> <version>${system.stubs.version}</version>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency>
<groupId>com.datastax.oss</groupId>
<artifactId>java-driver-mapper-runtime</artifactId>
<version>4.15.0</version>
</dependency>
</dependencies> </dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<annotationProcessorPaths>
<path>
<groupId>com.datastax.oss</groupId>
<artifactId>java-driver-mapper-processor</artifactId>
<version>4.15.0</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
</plugins>
</build>
<properties> <properties>
<java.version>11</java.version> <java.version>11</java.version>
<org.springframework.data.version>3.1.11</org.springframework.data.version> <org.springframework.data.version>3.1.11</org.springframework.data.version>

View File

@ -0,0 +1,12 @@
package org.baeldung.objectmapper;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class CassandraMapperApplication {
public static void main(String[] args) {
SpringApplication.run(CassandraMapperApplication.class, args);
}
}

View File

@ -0,0 +1,18 @@
package org.baeldung.objectmapper;
import com.datastax.oss.driver.api.core.CqlIdentifier;
import com.datastax.oss.driver.api.mapper.annotations.DaoFactory;
import com.datastax.oss.driver.api.mapper.annotations.DaoKeyspace;
import com.datastax.oss.driver.api.mapper.annotations.Mapper;
import org.baeldung.objectmapper.dao.CounterDao;
import org.baeldung.objectmapper.dao.UserDao;
@Mapper
public interface DaoMapper {
@DaoFactory
UserDao getUserDao(@DaoKeyspace CqlIdentifier keyspace);
@DaoFactory
CounterDao getUserCounterDao(@DaoKeyspace CqlIdentifier keyspace);
}

View File

@ -0,0 +1,16 @@
package org.baeldung.objectmapper.dao;
import com.datastax.oss.driver.api.mapper.annotations.Dao;
import com.datastax.oss.driver.api.mapper.annotations.Increment;
import com.datastax.oss.driver.api.mapper.annotations.Select;
import org.baeldung.objectmapper.entity.Counter;
@Dao
public interface CounterDao {
@Increment(entityClass = Counter.class)
void incrementCounter(String id, long count);
@Select
Counter getCounterById(String id);
}

View File

@ -0,0 +1,38 @@
package org.baeldung.objectmapper.dao;
import com.datastax.oss.driver.api.core.PagingIterable;
import com.datastax.oss.driver.api.core.cql.BoundStatement;
import com.datastax.oss.driver.api.core.cql.Row;
import com.datastax.oss.driver.api.mapper.annotations.*;
import org.baeldung.objectmapper.entity.User;
@Dao
public interface UserDao {
@Insert
void insertUser(User user);
@Select
User getUserById(int id);
@Select
PagingIterable<User> getAllUsers();
@Update
void updateUser(User user);
@Delete
void deleteUser(User user);
@GetEntity
User getUser(Row row);
@SetEntity
BoundStatement setUser(BoundStatement udtValue, User user);
@Query(value = "select * from user_profile where user_age > :userAge ALLOW FILTERING")
PagingIterable<User> getUsersOlderThanAge(int userAge);
@QueryProvider(providerClass = UserQueryProvider.class, entityHelpers = User.class, providerMethod = "getUsersOlderThanAge")
PagingIterable<User> getUsersOlderThan(String age);
}

View File

@ -0,0 +1,34 @@
package org.baeldung.objectmapper.dao;
import com.datastax.oss.driver.api.core.CqlSession;
import com.datastax.oss.driver.api.core.PagingIterable;
import com.datastax.oss.driver.api.core.cql.PreparedStatement;
import com.datastax.oss.driver.api.core.cql.SimpleStatement;
import com.datastax.oss.driver.api.mapper.MapperContext;
import com.datastax.oss.driver.api.mapper.entity.EntityHelper;
import com.datastax.oss.driver.api.querybuilder.QueryBuilder;
import org.baeldung.objectmapper.entity.User;
public class UserQueryProvider {
private final CqlSession session;
private final EntityHelper<User> userHelper;
public UserQueryProvider(MapperContext context, EntityHelper<User> userHelper) {
this.session = context.getSession();
this.userHelper = userHelper;
}
public PagingIterable<User> getUsersOlderThanAge(String age) {
SimpleStatement statement = QueryBuilder.selectFrom("user_profile")
.all()
.whereColumn("user_age")
.isGreaterThan(QueryBuilder
.bindMarker(age))
.build();
PreparedStatement preparedSelectUser = session.prepare(statement);
return session
.execute(preparedSelectUser.getQuery())
.map(result -> userHelper.get(result, true));
}
}

View File

@ -0,0 +1,31 @@
package org.baeldung.objectmapper.entity;
import com.datastax.oss.driver.api.mapper.annotations.CqlName;
import com.datastax.oss.driver.api.mapper.annotations.Entity;
import com.datastax.oss.driver.api.mapper.annotations.HierarchyScanStrategy;
@Entity
@CqlName("admin_profile")
@HierarchyScanStrategy(highestAncestor = User.class, includeHighestAncestor = true)
public class Admin extends User {
private String role;
private String department;
public String getRole() {
return role;
}
public void setRole(String role) {
this.role = role;
}
public String getDepartment() {
return department;
}
public void setDepartment(String department) {
this.department = department;
}
}

View File

@ -0,0 +1,29 @@
package org.baeldung.objectmapper.entity;
import com.datastax.oss.driver.api.mapper.annotations.Entity;
import com.datastax.oss.driver.api.mapper.annotations.PartitionKey;
@Entity
public class Counter {
@PartitionKey
private String id;
private long count;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public long getCount() {
return count;
}
public void setCount(long count) {
this.count = count;
}
}

View File

@ -0,0 +1,58 @@
package org.baeldung.objectmapper.entity;
import com.datastax.oss.driver.api.mapper.annotations.*;
@Entity
@CqlName("user_profile")
public class User {
@PartitionKey
private int id;
@CqlName("username")
private String userName;
@ClusteringColumn
private int userAge;
@Computed("writetime(userName)")
private long writetime;
public User() {
}
public User(int id, String userName, int userAge) {
this.id = id;
this.userName = userName;
this.userAge = userAge;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public int getUserAge() {
return userAge;
}
public void setUserAge(int userAge) {
this.userAge = userAge;
}
public long getWritetime() {
return writetime;
}
public void setWritetime(long writetime) {
this.writetime = writetime;
}
}

View File

@ -0,0 +1,96 @@
package org.baeldung.objectmapper;
import com.datastax.oss.driver.api.core.CqlIdentifier;
import com.datastax.oss.driver.api.core.CqlSession;
import org.baeldung.objectmapper.dao.CounterDao;
import org.baeldung.objectmapper.dao.UserDao;
import org.baeldung.objectmapper.entity.Counter;
import org.baeldung.objectmapper.entity.User;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import org.testcontainers.containers.CassandraContainer;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
import java.util.List;
@Testcontainers
@SpringBootTest
public class MapperLiveTest {
private static final String KEYSPACE_NAME = "baeldung";
@Container
private static final CassandraContainer cassandra = (CassandraContainer) new CassandraContainer("cassandra:3.11.2")
.withExposedPorts(9042);
static void setupCassandraConnectionProperties() {
System.setProperty("spring.data.cassandra.keyspace-name", KEYSPACE_NAME);
System.setProperty("spring.data.cassandra.contact-points", cassandra.getContainerIpAddress());
System.setProperty("spring.data.cassandra.port", String.valueOf(cassandra.getMappedPort(9042)));
}
static UserDao userDao;
static CounterDao counterDao;
@BeforeAll
static void setup() {
setupCassandraConnectionProperties();
CqlSession session = CqlSession.builder().build();
String createKeyspace = "CREATE KEYSPACE IF NOT EXISTS baeldung " +
"WITH replication = {'class':'SimpleStrategy', 'replication_factor':1};";
String useKeyspace = "USE baeldung;";
String createUserTable = "CREATE TABLE IF NOT EXISTS user_profile " +
"(id int, username text, user_age int, writetime bigint, PRIMARY KEY (id, user_age)) " +
"WITH CLUSTERING ORDER BY (user_age DESC);";
String createAdminTable = "CREATE TABLE IF NOT EXISTS admin_profile " +
"(id int, username text, user_age int, role text, writetime bigint, department text, " +
"PRIMARY KEY (id, user_age)) " +
"WITH CLUSTERING ORDER BY (user_age DESC);";
String createCounter = "CREATE TABLE IF NOT EXISTS counter " +
"(id text, count counter, PRIMARY KEY (id));";
session.execute(createKeyspace);
session.execute(useKeyspace);
session.execute(createUserTable);
session.execute(createAdminTable);
session.execute(createCounter);
DaoMapper mapper = new DaoMapperBuilder(session).build();
userDao = mapper.getUserDao(CqlIdentifier.fromCql("baeldung"));
counterDao = mapper.getUserCounterDao(CqlIdentifier.fromCql("baeldung"));
}
@Test
void givenUser_whenInsert_thenRetrievedDuringGet() {
User user = new User(1, "JohnDoe", 31);
userDao.insertUser(user);
User retrievedUser = userDao.getUserById(1);
Assertions.assertEquals(retrievedUser.getUserName(), user.getUserName());
}
@Test
void givenCounter_whenIncrement_thenIncremented() {
Counter users = counterDao.getCounterById("users");
long initialCount = users != null ? users.getCount(): 0;
counterDao.incrementCounter("users", 1);
users = counterDao.getCounterById("users");
long finalCount = users != null ? users.getCount(): 0;
Assertions.assertEquals(finalCount - initialCount, 1);
}
@Test
void givenUser_whenGetUsersOlderThan_thenRetrieved() {
User user = new User(2, "JaneDoe", 20);
userDao.insertUser(user);
List<User> retrievedUsers = userDao.getUsersOlderThanAge(30).all();
Assertions.assertEquals(retrievedUsers.size(), 1);
}
}