Skip to content

5 minutes Tutorial

DuyHai DOAN edited this page Dec 24, 2014 · 32 revisions

Bootstrap

First of all you need to initialize the PersistenceManagerFactory.

PersistenceManagerFactory persistenceManagerFactory = PersistenceManagerFactory.PersistenceManagerFactoryBuilder
.builder()
.withEntityPackages("my.package1,my.package2")
.withConnectionContactPoints("localhost")
.withCQLPort(9041)
.withKeyspaceName("Test Keyspace")
.forceTableCreation(true).build();

The forceTableCreation(true) parameter tells Achilles to force the tables creation if they do not exist or not.

This flag should be set to false most of the time when going to Prod. Set it to true during development phase because Achilles creates its own column family structure for insertion and it is very unlikely that your existing column families are compatible with Achilles structure (but it can be in some cases, check DDL Scripts Generation)

Once the factory bean is defined, you can just inject the PersistenceManager into any of your service

	@Inject
	private PersistenceManager manager;
	...

Bean Mapping

Let's create an User bean

    import info.archinnov.achilles.annotations.Column;
    import info.archinnov.achilles.annotations.PartitionKey;
     
    @Entity(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 ...
    }
    
    public class Biography 
    {
        private String birthPlace;
        private List<String> diplomas;
        private String description; 
        
        //Getters and Setters
    }

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
    manager.insert(user);

Then we can find it by id:

    User foundUser = manager.find(User.class,1L);
        
    // Now add some new tags
    foundUser.getFavoriteTags().add("achilles"); 
        
    // Update it
    manager.update(foundUser);

Clustered entities

To use Cassandra native wide rows structure, you can define a clustered entity. An entity is clustered when it has an @CompoundPrimaryKey and the following properties:

  1. at least one, possibly many fields annotated with @PartitionKey. This field represents the partition key. If many @PartitionKey are used, the partition key is composite
  2. at least one, possibly many fields annotated with @ClusteringColumn representing clustering columns. There can be 0 clustering column if you have a composite partition key
  3. the order of each component can be defined using the value attribute of those annotations. It defaults to 1 if not set
  4. for reversed clustering column, you can use the reversed attribute of the @ClusteringColumn annotation
  5. you may add @Column annotation in addition to the above annotations to define a specific column name in cassandra, using the name attribute
    @Entity(table="timeline")
    public class Timeline
    {
        @CompoundPrimaryKey
        private TweetKey id;
    
        @Column
        private Tweet tweet;
    
        public Timeline(Long userId,Tweet tweet)
        {
            this.id = new TweetKey(userId,tweet.getId());
            this.tweet = tweet;
        }
    
    
        public static class TweetKey 
        {
            @PartitionKey 
            private Long userId;
    
            @ClusteringColumn
            private UUID tweetId;
    
            public TweetKey(){}
    
            public TweetKey(Long userId, UUID tweetId)
            {
                this.userId = userId;
                this.tweetId = tweetId;
            }
        }
    }

Tweet here is a simple POJO.

To insert new tweets to the user timeline:

    Long userId = user.getId();
        
    Tweet tweet1 = new Tweet(), tweet2 = new Tweet(), 
          tweet3 = new Tweet(), tweet4 = new Tweet();
        
        
    // Insert tweets
    manager.insert(new Timeline(userid,tweet1));
    manager.insert(new Timeline(userid,tweet2));
    manager.insert(new Timeline(userid,tweet3));
        
    // Insert with TTL
    manager.insert(new Timeline(userid,tweet4),OptionsBuilder.withTtl(150));
    
    ...
    ...

Later, you can retrieved the saved tweets using SliceQueryBuilder :

    // Should return tweet2 & tweet3
    List<Timeline> foundRange = manager.sliceQuery(Timeline.class)
        .forSelect()
        .withPartitionComponents(userId)
        .fromClusterings(uuid2)
        .toClusterings(uuid4)
        .limit(10)
        .fromInclusiveToExclusiveBounds()
        .orderByAscending()
        .get();
        
    assertEquals(foundRange.size(),2);	
        
    // Assuming that you implemented equals() & hashCode() for Tweet class
    assertEquals(foundRange.get(0).getTweet(),tweet2); 
    assertEquals(foundRange.get(1).getTweet(),tweet3);

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

Home

Clone this wiki locally