Lightweight-Transaction

Achilles offers a complete support for Lightweight Transaction (LWT) feature

LWT for insertions

To insert an entity if it does not exist (using the IF NOT EXISTS clause in CQL):


    manager
        .crud()
        .insert(new MyEntity(...))
        .ifNotExists()
        .execute();

LWT for deletions

To delete an entity if it already exists (using the IF EXISTS clause in CQL):

On the CRUD API


    manager
        .crud()
        .deleteById(...)
        .ifExists()
        .execute();
        

On the DSL API


    manager
        .dsl()
        .delete()
        ...
        .ifExists()
        .execute();
        

LWT for conditional updates or deletions

    
    @Table(table = "user")
    public class User {
        @PartitionKey
        private Long id;
    
        @Column
        private String login;
    
        @Column
        private String name;
        
        @Column
        private Integer credits;
    }

    ... 

    // Conditional updates
    manager
        .dsl()
        .update()
        .fromBaseTable()
        .where()
        ...
        .ifExists()
        .execute();
        
    manager
        .dsl()
        .update()
        .fromBaseTable()
        ...
        .credits().Set(...) //set new credits
        ...
        .where()
        .if_Credits().Eq(...) //check for previous credits value
        .execute();
        
    manager
        .dsl()
        .update()
        .fromBaseTable()
        ...
        .credits().Set(...) //set new credits
        .where()
        ...
        .if_Credits().Gte(...) //check for previous credits value >=
        .execute();

    // Conditional delete
    manager
        .dsl()
        .delete()
        ....
        .where()
        ...
        .ifExists()
        .execute();
                

    manager
        .dsl()
        .delete()
        ....
        .where()
        ...
        .if_Credits().Eq(...) //check for previous credits value
        .execute();
                            

Please note that non equal conditions are only available since
Cassandra 2.1.2. Those conditions are not supported for prior versions.

LWT Result Listener

To have tighter control on LWT updates or inserts, Achilles lets you inject a listener for LWT operations result


    LWTResultListener lwtListener = new LWTResultListener() {

        default void onSuccess() {
            // Do something on success
            // Default behavior is an no-op
        }
    
        public void onError(LWTResult lwtResult) {
        
            //Get type of LWT operation that fails
            LWTResult.Operation operation = lwtResult.operation();
            
            // Print out current values
            TypedMap currentValues = lwtResult.currentValues(); 
            for(Entry<String,Object> entry: currentValues.entrySet()) {
                System.out.println(String.format("%s = %s",entry.getKey(), entry.getValue()));          
            }
        }
    };

    manager
        .dsl()
        .update()
        ...
        .withLwtResultListener(lwtListener)
        .execute();

Let's take a concrete example. Suppose you have inserted in the user table the following data:


    INSERT INTO user(id,login,name) VALUES(10,'johndoe','John DOE');

Now you try to update with OptionsBuilder.lwtEqualCondition("login","jdoe")


    UPDATE user SET name = 'Johnny DOE' WHERE id=10 IF login='jdoe';
    
     [applied] | login
    -----------+-------
         False |  johndoe

Had you registered a LWTResultListener, the returned TypedMap of LWTResult.currentValues() would contain:

Remark: it is possible to register multiple LWT listeners


LWT Serial Consistency

It is also possible to define Serial consistency level at runtime for LWT operations


    manager
        .dsl()
        .update()
        ...
        .withSerialConsistency(...)
        .execute();