Skip to content

Lightweight Transaction

DuyHai DOAN edited this page Aug 25, 2017 · 9 revisions

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:

  • key: "[applied]", value: false (boolean)
  • key: "login", value: "johndoe" (String)

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();
		  

Home

Clone this wiki locally