diff --git a/persistence-modules/spring-data-cassandra-2/pom.xml b/persistence-modules/spring-data-cassandra-2/pom.xml
index 1e6412dc17..740c04d2a0 100644
--- a/persistence-modules/spring-data-cassandra-2/pom.xml
+++ b/persistence-modules/spring-data-cassandra-2/pom.xml
@@ -60,8 +60,32 @@
${system.stubs.version}
test
+
+ com.datastax.oss
+ java-driver-mapper-runtime
+ 4.15.0
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ 3.8.1
+
+
+
+ com.datastax.oss
+ java-driver-mapper-processor
+ 4.15.0
+
+
+
+
+
+
+
11
3.1.11
diff --git a/persistence-modules/spring-data-cassandra-2/src/main/java/org/baeldung/objectmapper/CassandraMapperApplication.java b/persistence-modules/spring-data-cassandra-2/src/main/java/org/baeldung/objectmapper/CassandraMapperApplication.java
new file mode 100644
index 0000000000..da66ee1401
--- /dev/null
+++ b/persistence-modules/spring-data-cassandra-2/src/main/java/org/baeldung/objectmapper/CassandraMapperApplication.java
@@ -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);
+ }
+}
diff --git a/persistence-modules/spring-data-cassandra-2/src/main/java/org/baeldung/objectmapper/DaoMapper.java b/persistence-modules/spring-data-cassandra-2/src/main/java/org/baeldung/objectmapper/DaoMapper.java
new file mode 100644
index 0000000000..f7e937702d
--- /dev/null
+++ b/persistence-modules/spring-data-cassandra-2/src/main/java/org/baeldung/objectmapper/DaoMapper.java
@@ -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);
+}
\ No newline at end of file
diff --git a/persistence-modules/spring-data-cassandra-2/src/main/java/org/baeldung/objectmapper/dao/CounterDao.java b/persistence-modules/spring-data-cassandra-2/src/main/java/org/baeldung/objectmapper/dao/CounterDao.java
new file mode 100644
index 0000000000..71978ce116
--- /dev/null
+++ b/persistence-modules/spring-data-cassandra-2/src/main/java/org/baeldung/objectmapper/dao/CounterDao.java
@@ -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);
+}
diff --git a/persistence-modules/spring-data-cassandra-2/src/main/java/org/baeldung/objectmapper/dao/UserDao.java b/persistence-modules/spring-data-cassandra-2/src/main/java/org/baeldung/objectmapper/dao/UserDao.java
new file mode 100644
index 0000000000..9e06066c1e
--- /dev/null
+++ b/persistence-modules/spring-data-cassandra-2/src/main/java/org/baeldung/objectmapper/dao/UserDao.java
@@ -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 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 getUsersOlderThanAge(int userAge);
+
+ @QueryProvider(providerClass = UserQueryProvider.class, entityHelpers = User.class, providerMethod = "getUsersOlderThanAge")
+ PagingIterable getUsersOlderThan(String age);
+}
diff --git a/persistence-modules/spring-data-cassandra-2/src/main/java/org/baeldung/objectmapper/dao/UserQueryProvider.java b/persistence-modules/spring-data-cassandra-2/src/main/java/org/baeldung/objectmapper/dao/UserQueryProvider.java
new file mode 100644
index 0000000000..10c56a9310
--- /dev/null
+++ b/persistence-modules/spring-data-cassandra-2/src/main/java/org/baeldung/objectmapper/dao/UserQueryProvider.java
@@ -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 userHelper;
+
+ public UserQueryProvider(MapperContext context, EntityHelper userHelper) {
+ this.session = context.getSession();
+ this.userHelper = userHelper;
+ }
+
+ public PagingIterable 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));
+ }
+}
diff --git a/persistence-modules/spring-data-cassandra-2/src/main/java/org/baeldung/objectmapper/entity/Admin.java b/persistence-modules/spring-data-cassandra-2/src/main/java/org/baeldung/objectmapper/entity/Admin.java
new file mode 100644
index 0000000000..afd6b74490
--- /dev/null
+++ b/persistence-modules/spring-data-cassandra-2/src/main/java/org/baeldung/objectmapper/entity/Admin.java
@@ -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;
+ }
+
+}
+
diff --git a/persistence-modules/spring-data-cassandra-2/src/main/java/org/baeldung/objectmapper/entity/Counter.java b/persistence-modules/spring-data-cassandra-2/src/main/java/org/baeldung/objectmapper/entity/Counter.java
new file mode 100644
index 0000000000..88b49b561e
--- /dev/null
+++ b/persistence-modules/spring-data-cassandra-2/src/main/java/org/baeldung/objectmapper/entity/Counter.java
@@ -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;
+ }
+
+}
diff --git a/persistence-modules/spring-data-cassandra-2/src/main/java/org/baeldung/objectmapper/entity/User.java b/persistence-modules/spring-data-cassandra-2/src/main/java/org/baeldung/objectmapper/entity/User.java
new file mode 100644
index 0000000000..31612ffe73
--- /dev/null
+++ b/persistence-modules/spring-data-cassandra-2/src/main/java/org/baeldung/objectmapper/entity/User.java
@@ -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;
+ }
+}
\ No newline at end of file
diff --git a/persistence-modules/spring-data-cassandra-2/src/test/java/org/baeldung/objectmapper/MapperLiveTest.java b/persistence-modules/spring-data-cassandra-2/src/test/java/org/baeldung/objectmapper/MapperLiveTest.java
new file mode 100644
index 0000000000..b61663d622
--- /dev/null
+++ b/persistence-modules/spring-data-cassandra-2/src/test/java/org/baeldung/objectmapper/MapperLiveTest.java
@@ -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 retrievedUsers = userDao.getUsersOlderThanAge(30).all();
+ Assertions.assertEquals(retrievedUsers.size(), 1);
+ }
+
+}
\ No newline at end of file