Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the most efficient way to map/transform/cast a Cassandra BoundStatement's ResultSet to a Java classe built using the Object-mapping API?

Is there a builtin way in DataStax Java for Apache Cassandra to map the ResultSet coming from a BoundStatement to the domain objects Java classes built with using the Object-mapping API?

I am a newbie moving from the Mapper + Accessor approach to BoundStatement approach and would like to continue using the domain objects' Java classes built with the Object-mapping API so I do minimal changes to the implementation of my DAO methods while moving to the BoundStatement. I am looking to do it in a generic way and avoid to iterate over each ResultSet row and do a row.get one by one for each domain object.

While using the Mapper + Accessor approach, the Result.all() do that very well. Could not find anything similar to the BoundStatement approach.

Thanks

IPVP

like image 707
user3395041 Avatar asked Jan 10 '16 03:01

user3395041


2 Answers

You can accomplish mapping a ResultSet to a com.datastax.driver.mapping.Result by instantiating a Mapper for your object, and then using Mapper.map. Here is an example, taken from the java driver's tests that takes a ResultSet from a regularly executed query and maps it to a Result<Post>, and then iterates over the Result to access each mapped Post:

MappingManager manager = new MappingManager(session);

Mapper<Post> m = manager.mapper(Post.class);
...
// Retrieve posts with a projection query that only retrieves some of the fields
ResultSet rs = session.execute("select user_id, post_id, title from posts where user_id = " + u1.getUserId());

Result<Post> result = m.map(rs);
for (Post post : result) {
    assertThat(post.getUserId()).isEqualTo(u1.getUserId());
    assertThat(post.getPostId()).isNotNull();
    assertThat(post.getTitle()).isNotNull();

    assertThat(post.getDevice()).isNull();
    assertThat(post.getTags()).isNull();
}
like image 87
Andy Tolbert Avatar answered Nov 02 '22 01:11

Andy Tolbert


Starting from version 4.1.0 of the DataStax Java Driver, there is a different way to map objects using the new object mapper.

The code from Andy Tolbert's answer would be something like the code below.

First, we need to enable the annotation processor. Using Maven, add the following to pom.xml:

<build>
    <plugins>
        <plugin>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.8.1</version>
            <configuration>
                <source>1.8</source>
                <target>1.8</target>
                <annotationProcessorPaths>
                    <path>
                        <groupId>com.datastax.oss</groupId>
                        <artifactId>java-driver-mapper-processor</artifactId>
                        <version>4.4.0</version>
                    </path>
                </annotationProcessorPaths>
            </configuration>
        </plugin>
    </plugins>
</build>

Let's assume there is a keyspace called posts, with a single table posts that has columns user_id, post_id and title.

We need to create a class called Post (which we'll map to table name posts using @CqlName annotation) as below.

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.PartitionKey;

@Entity
@CqlName("posts")
public class Post {

    @PartitionKey
    private String postId;
    private String title;
    private String userId;

    // add getters/setters/no-args constructor/equals/hashCode
}

Now we create an interface called PostDao, which has the queries we want to execute.

import com.datastax.oss.driver.api.mapper.annotations.Dao;
import com.datastax.oss.driver.api.mapper.annotations.Select;

@Dao
public interface PostDao {

    @Select
    Post findById(String postId);
}

Finally, we create an interface for the mapper.

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;

@Mapper
public interface PostMapper {

    @DaoFactory
    PostDao postDao(@DaoKeyspace CqlIdentifier keyspace);
}

When we run mvn compile, the annotation processor will generate a class called PostMapperBuilder (which we'll need for running the queries).

CqlSession session = CqlSession.builder().build();

PostMapper postMapper = new PostMapperBuilder(session).build();

PostDao dao = postMapper.postDao(CqlIdentifier.fromCql("posts"));

Post post = dao.findById("a1b2c3d4"); // or whatever the postId is...

Be sure to check out the documentation on configuring the annotation processor and on creating entities.

like image 4
brunobastosg Avatar answered Nov 02 '22 01:11

brunobastosg