DATACASS-182 - Add ability to update/store null into fields.

We now support the removal of columns for properties with null values by allowing null values in Insert and Update statements written by MappingCassandraConverter. Objects are stored with all persistent properties. Insert and update perform no longer conditional inserting of non-null values but take all values into account.

Original pull request: #72.
This commit is contained in:
Mark Paluch
2016-06-28 13:45:57 +02:00
committed by John Blum
parent f30468627d
commit e10c71722d
6 changed files with 136 additions and 15 deletions

View File

@@ -272,12 +272,10 @@ public class MappingCassandraConverter extends AbstractCassandraConverter
return;
}
if (value != null) {
if (log.isDebugEnabled()) {
log.debug("Adding insert.value [{}] - [{}]", prop.getColumnName().toCql(), value);
}
insert.value(prop.getColumnName().toCql(), value);
if (log.isDebugEnabled()) {
log.debug("Adding insert.value [{}] - [{}]", prop.getColumnName().toCql(), value);
}
insert.value(prop.getColumnName().toCql(), value);
}
});
}
@@ -303,12 +301,10 @@ public class MappingCassandraConverter extends AbstractCassandraConverter
return;
}
if (value != null) {
if (prop.isIdProperty() || entity.isCompositePrimaryKey() || prop.isPrimaryKeyColumn()) {
update.where(QueryBuilder.eq(prop.getColumnName().toCql(), value));
} else {
update.with(QueryBuilder.set(prop.getColumnName().toCql(), value));
}
if (isPrimaryKeyPart(prop)) {
update.where(QueryBuilder.eq(prop.getColumnName().toCql(), value));
} else {
update.with(QueryBuilder.set(prop.getColumnName().toCql(), value));
}
}
});
@@ -444,4 +440,14 @@ public class MappingCassandraConverter extends AbstractCassandraConverter
return new ConvertingPropertyAccessor(accessor, conversionService);
}
/**
* Returns whether the property is part of the primary key.
*
* @param property
* @return
*/
private boolean isPrimaryKeyPart(CassandraPersistentProperty property) {
return property.isCompositePrimaryKey() || property.isPrimaryKeyColumn() || property.isIdProperty();
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2013-2014 the original author or authors
* Copyright 2013-2016 the original author or authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -32,6 +32,7 @@ import com.datastax.driver.core.querybuilder.Select;
*
* @author Alex Shvid
* @author Matthew T. Adams
* @author Mark Paluch
*/
public class SimpleCassandraRepository<T, ID extends Serializable> implements TypedIdCassandraRepository<T, ID> {

View File

@@ -103,7 +103,7 @@ public class MappingCassandraConverterUnitTests {
mappingCassandraConverter.write(withEnumColumns, insert);
assertThat(getValues(insert), contains((Object) "MINT"));
assertThat(getValues(insert), hasItem((Object) "MINT"));
}
/**

View File

@@ -19,6 +19,8 @@ import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
@@ -34,13 +36,16 @@ import org.springframework.cassandra.core.RetryPolicy;
import org.springframework.cassandra.core.WriteOptions;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.cassandra.core.CassandraOperations;
import org.springframework.data.cassandra.core.CassandraTemplate;
import org.springframework.data.cassandra.test.integration.simpletons.Book;
import org.springframework.data.cassandra.test.integration.simpletons.BookCondition;
import org.springframework.data.cassandra.test.integration.simpletons.BookReference;
import org.springframework.data.cassandra.test.integration.support.AbstractSpringDataEmbeddedCassandraIntegrationTest;
import org.springframework.data.cassandra.test.integration.support.IntegrationTestConfig;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import com.datastax.driver.core.querybuilder.Delete;
import com.datastax.driver.core.querybuilder.QueryBuilder;
import com.datastax.driver.core.querybuilder.Select;
@@ -691,7 +696,6 @@ public class CassandraOperationsIntegrationTests extends AbstractSpringDataEmbed
assertThat(template.count(Book.class), is(equalTo(count)));
}
@Test
public void insertAndSelect() {
@@ -703,6 +707,90 @@ public class CassandraOperationsIntegrationTests extends AbstractSpringDataEmbed
assertThat(template.count(Book.class), is(equalTo(count)));
}
/**
* @see DATACASS-182
*/
@Test
public void updateShouldRemoveFields() {
Book book = new Book();
book.setIsbn("isbn");
book.setTitle("title");
book.setAuthor("author");
template.insert(book);
book.setTitle(null);
template.update(book);
Book loaded = template.selectOneById(Book.class, book.getIsbn());
assertThat(loaded.getTitle(), is(nullValue()));
assertThat(loaded.getAuthor(), is(equalTo("author")));
}
/**
* @see DATACASS-182
*/
@Test
public void insertShouldRemoveFields() {
Book book = new Book();
book.setIsbn("isbn");
book.setTitle("title");
book.setAuthor("author");
template.insert(book);
book.setTitle(null);
template.insert(book);
Book loaded = template.selectOneById(Book.class, book.getIsbn());
assertThat(loaded.getTitle(), is(nullValue()));
assertThat(loaded.getAuthor(), is(equalTo("author")));
}
/**
* @see DATACASS-182
*/
@Test
public void updateShouldInsertEntity() {
Book book = new Book();
book.setIsbn("isbn");
book.setTitle("title");
book.setAuthor("author");
template.update(book);
Book loaded = template.selectOneById(Book.class, book.getIsbn());
assertThat(loaded, is(notNullValue()));
}
/**
* @see DATACASS-182
*/
@Test
public void insertAndUpdateToEmptyCollection() {
BookReference bookReference = new BookReference();
bookReference.setIsbn("isbn");
bookReference.setBookmarks(Arrays.asList(1, 2, 3, 4));
template.insert(bookReference);
bookReference.setBookmarks(Collections.<Integer> emptyList());
template.update(bookReference);
BookReference loaded = template.selectOneById(BookReference.class, bookReference.getIsbn());
assertThat(loaded.getTitle(), is(nullValue()));
assertThat(loaded.getBookmarks(), is(nullValue()));
}
/**
* @see DATACASS-297
*/

View File

@@ -19,6 +19,7 @@ import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import org.junit.Assert;
@@ -32,6 +33,7 @@ import com.google.common.collect.Lists;
* @author Alex Shvid
* @author Matthew T. Adams
* @author David Webb
* @author Mark Paluch
*/
public class UserRepositoryIntegrationTests {
@@ -150,6 +152,22 @@ public class UserRepositoryIntegrationTests {
}
/**
* @see DATACASS-182
*/
public void save() {
tom.setPassword(null);
tom.setFriends(Collections.<String>emptySet());
repository.save(tom);
User loadedTom = repository.findOne(tom.getUsername());
assertThat(loadedTom.getPassword(), is(nullValue()));
assertThat(loadedTom.getFriends(), is(nullValue()));
}
private static void assertEquals(User user1, User user2) {
Assert.assertEquals(user1.getUsername(), user2.getUsername());
Assert.assertEquals(user1.getFirstName(), user2.getFirstName());
@@ -157,5 +175,4 @@ public class UserRepositoryIntegrationTests {
Assert.assertEquals(user1.getPlace(), user2.getPlace());
Assert.assertEquals(user1.getPassword(), user2.getPassword());
}
}

View File

@@ -26,6 +26,7 @@ import org.springframework.data.cassandra.test.integration.support.AbstractSprin
*
* @author Matthew T. Adams
* @author David Webb
* @author Mark Paluch
*/
public abstract class UserRepositoryIntegrationTestsDelegator
extends AbstractSpringDataEmbeddedCassandraIntegrationTest {
@@ -75,4 +76,12 @@ public abstract class UserRepositoryIntegrationTestsDelegator
public void exists() {
tests.exists();
}
/**
* @see DATACASS-182
*/
@Test
public void save() {
tests.save();
}
}