5 minutes Tutorial

DuyHai DOAN edited this page Sep 6, 2016 · 32 revisions

Home

Clone this wiki locally

First, make sure that you have configured your IDE correctly, otherwise, read the IDE Configuration section first

Compile time configuration

Before creating any class, we should tell Achilles the version of Cassandra we're using. For this, just create an empty class/interface annotated with @CompileTimeConfig

    @CompileTimeConfig(cassandraVersion = CassandraVersion.CASSANDRA_3_0_X)
    public interface AchillesConfig {

    }

Here we specify that we are using Cassandra version 3.0.X. Depending on the chosen version, Achilles will generate appropriate DSL code. You can also specify the column mapping strategy, naming strategy, insert strategy and the project name.

See Configuring Achilles at compile time for more details

Bean Mapping

Let's create an User bean

    import info.archinnov.achilles.annotations.Column;
    import info.archinnov.achilles.annotations.PartitionKey;

    @Table(table="users") 
    public class User 
    {
        @PartitionKey
        private Long id;

        @Column
        private String firstname;

        @Column
        private String lastname;

        @Column(name="age_in_year")
        private Integer age;

        @Column
        private Biography bio;

        @Column
        private List<String> favoriteTags;

        @Column
        private Map<Integer,String> preferences;

        // Getters and setters ...
    }

    @UDT(keyspace="Test Keyspace", name = "bio_udt")
    public class Biography 
    {
        @Column
        private String birthPlace;

        @Column
        private List<String> diplomas;

        @Column
        private String description; 

        //Getters and Setters
    }

Now compile/rebuild your project so that Achilles annotation processor can generate the relevant meta classes.

Bootstrap

Then you need to initialize the Manager instance for your User entity.

    Cluster cluster = Cluster.builder()....build();
    ManagerFactory managerFactory = ManagerFactoryBuilder
        .builder(cluster)
        .withDefaultKeyspaceName("Test Keyspace")
        .doForceSchemaCreation(true)
        .build();

    User_Manager manager = managerFactory.forUser();

The doForceSchemaCreation(true) parameter asks Achilles to force the tables creation if they do not exist. This flag should be set to false most of the time when going to Production. Set it to true during development phase to let Achilles do the work for you. You can track the schema creation statements by looking at DDL Scripts Generation)

Once the manager instance is defined, you can just inject it into any of your service

    @Inject
    private User_Manager manager;
    ...

Hint: Achilles generated classes follow a very simple convention. Generated manager class is named as <your-entity-classname>_Manager

Usage

First we create an User and insert it

    User user = new User();
    user.setId(1L);
    user.setFirstname("DuyHai");
    user.setLastname("DOAN");
    user.setAge(30);

    // Biography
    Biography bio = new Biography();
    bio.setBirthPlace("VietNam");
    bio.setDiplomas(Arrays.asList("Master of Science","Diplome d'ingenieur"));
    bio.setDescription("Yet another framework developer");  
    user.setBio(bio);

    // Favorite Tags
    Set<String> tags = new HashSet<String>();
    tags.add("computing");
    tags.add("java");
    tags.add("cassandra");
    user.setFavoriteTags(tags);

    // Preferences
    Map<Integer,String> preferences = new HashMap<Integer,String>();
    preferences.put(1,"FR");
    preferences.put(2,"French");
    preferences.put(3,"Paris");

    user.setPreferences(preferences);

    // Save user using the CRUD API
    manager
        .crud()
        .insert(user)
        .execute();

Then we can find it by id:

    // Find user by id using the CRUD API
    User foundUser = manager
                        .crud()
                        .findById(1L);

    // Now add anew favorite tag to this user by using the DSL API
    manager
        .dsl()
        .update()
        .fromBaseTable()
        .favoriteTags().AddTo("achilles")
        .where()
        .id().Eq(1L)
        .execute();

Clustered entities

To use Cassandra native wide partitions, you can define a clustered entity. An entity is clustered when it has at least one clustering column

    @Table(table="timeline")
    public class Timeline
    {
        @PartitionKey
        @Column("user_id") 
        private Long userId;

        @ClusteringColumn
        @Column("tweet_id")
        private UUID tweetId;

        @Column("tweet_content")
        private String tweetContent;

        public Timeline(Long userId, UUID tweetId, String tweetContent)
        {
            this.userId = userId;
            this.tweetId = tweetId;
            this.tweetContent = tweetContent;
        }

        //Getters & Setters
    }

To insert new tweets to the user timeline:

    Long userId = user.getId();

    UUID tweetId1 = ...;
    UUID tweetId2 = ...;
    UUID tweetId3 = ...;
    UUID tweetId4 = ...;


    // Insert tweets using the CRUD API
    manager.crud().insert(new Timeline(userId,tweetId1, "content ...")).execute();
    manager.crud().insert(new Timeline(userId,tweetId2, "content ...")).execute();
    manager.crud().insert(new Timeline(userId,tweetId3, "content ...")).execute();

    // Insert using the CRUD API with options (TTL)
    manager
        .crud()
        .insert(new Timeline(userId,tweet4Id, "content ..."))
        .usingTimeToLive(100)
        .execute();

    ...
    ...

Later, you can retrieved the saved tweets using the generated DSL API :

    UUID uuid2 = ...:
    UUID uuid4 = ...:

    // Use the DSL API to get a list of tweets
    List<Timeline> foundRange = manager
        .dsl()
        .select()
        .allColumns_FromBaseTable()
        .where()
        .id().Eq(userId)
        .tweetId().Gte_And_Lt(uuid2, uuid4)
        .orderByAscending()
        .limit(10)
        .getList();

    assertEquals(foundRange.size(),2);  
    assertEquals(foundRange.get(0).getTweetContent(), "content ..."); 
    assertEquals(foundRange.get(1).getTweetContent(), "content ...");

And that's it. To have more details on the advanced features, please check the Documentation.