Java tutorial
/* * Copyright (C) 2012-2014 DuyHai DOAN * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package info.archinnov.achilles.test.integration.tests; import static info.archinnov.achilles.embedded.ServerStarter.CASSANDRA_EMBEDDED; import static info.archinnov.achilles.persistence.PersistenceManagerFactory.PersistenceManagerFactoryBuilder; import static org.fest.assertions.api.Assertions.assertThat; import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.Set; import java.util.UUID; import info.archinnov.achilles.annotations.*; import org.apache.commons.lang3.RandomUtils; import org.junit.Test; import com.datastax.driver.core.Cluster; import com.datastax.driver.core.Session; import com.google.common.collect.ImmutableMap; import info.archinnov.achilles.embedded.CassandraEmbeddedServerBuilder; import info.archinnov.achilles.exception.AchillesInvalidTableException; import info.archinnov.achilles.internal.utils.UUIDGen; import info.archinnov.achilles.persistence.PersistenceManager; import info.archinnov.achilles.persistence.PersistenceManagerFactory; import info.archinnov.achilles.test.integration.entity.CompleteBean; import info.archinnov.achilles.type.Counter; import info.archinnov.achilles.type.CounterBuilder; public class SchemaUpdateIT { @Test public void should_allow_dynamic_schema_update() throws Exception { //Given Long id = RandomUtils.nextLong(0, Long.MAX_VALUE); final Session session = CassandraEmbeddedServerBuilder.noEntityPackages() .withKeyspaceName("schema_dynamic_update").cleanDataFilesAtStartup(true).buildNativeSessionOnly(); session.execute("DROP TABLE IF EXISTS new_simple_field"); session.execute("DROP INDEX IF EXISTS field_index"); session.execute("CREATE TABLE new_simple_field(id bigint PRIMARY KEY, existing_field text)"); session.execute("CREATE INDEX field_index ON schema_dynamic_update.new_simple_field(existing_field)"); //When final PersistenceManagerFactory pmf = PersistenceManagerFactoryBuilder.builder(session.getCluster()) .withNativeSession(session).withEntities(Arrays.<Class<?>>asList(EntityWithNewSimpleField.class)) .enableSchemaUpdate(false) .enableSchemaUpdateForTables(ImmutableMap.of("schema_dynamic_update.new_simple_field", true)) .relaxIndexValidation(true).build(); final PersistenceManager pm = pmf.createPersistenceManager(); pm.insert(new EntityWithNewSimpleField(id, "existing", "new")); //Then final EntityWithNewSimpleField found = pm.find(EntityWithNewSimpleField.class, id); assertThat(found).isNotNull(); assertThat(found.getUnmappedField()).isEqualTo("UNMAPPED"); assertThat(pm.find(EntityWithNewSimpleField.class, id).getUnmappedField()).isEqualTo("UNMAPPED"); session.close(); } @Test public void should_allow_dynamic_schema_update_for_cluster_counter() throws Exception { //Given Long id = RandomUtils.nextLong(0, Long.MAX_VALUE); UUID date = UUIDGen.getTimeUUID(); final Session session = CassandraEmbeddedServerBuilder .withEntities(Arrays.<Class<?>>asList(CompleteBean.class)) .withKeyspaceName("schema_dynamic_update_counter").cleanDataFilesAtStartup(true) .buildNativeSessionOnly(); session.execute("DROP TABLE IF EXISTS new_counter_field"); session.execute( "CREATE TABLE new_counter_field(id bigint, date timeuuid, existing_counter counter, PRIMARY KEY(id,date))"); //When final PersistenceManagerFactory pmf = PersistenceManagerFactoryBuilder.builder(session.getCluster()) .withEntities(Arrays.<Class<?>>asList(ClusteredCounterEntityWithNewCounterField.class)) .enableSchemaUpdate(true).build(); final PersistenceManager pm = pmf.createPersistenceManager(); pm.insert(new ClusteredCounterEntityWithNewCounterField(id, date, CounterBuilder.incr(12L))); //Then assertThat(pm.find(ClusteredCounterEntityWithNewCounterField.class, new ClusteredCounterEntityWithNewCounterField.Compound(id, date))).isNotNull(); session.close(); } @Test(expected = AchillesInvalidTableException.class) public void should_fail_bootstrapping_if_schema_update_forbidden_for_entity() throws Exception { //Given final Session session = CassandraEmbeddedServerBuilder.noEntityPackages() .withKeyspaceName("schema_dynamic_update_fail").cleanDataFilesAtStartup(true) .buildNativeSessionOnly(); session.execute("DROP TABLE IF EXISTS new_simple_field"); session.execute("CREATE TABLE new_simple_field(id bigint PRIMARY KEY, existing_field text)"); //When PersistenceManagerFactoryBuilder.builder(session.getCluster()) .withEntities(Arrays.<Class<?>>asList(EntityWithNewSimpleField.class)) .withKeyspaceName("schema_dynamic_update_fail").enableSchemaUpdate(true) .enableSchemaUpdateForTables(ImmutableMap.of("schema_dynamic_update_fail.new_simple_field", false)) .build(); session.close(); } @Test(expected = AchillesInvalidTableException.class) public void should_fail_bootstrapping_if_index_validation_fails() throws Exception { //Given final Session session = CassandraEmbeddedServerBuilder.noEntityPackages() .withKeyspaceName("schema_dynamic_update").cleanDataFilesAtStartup(true).buildNativeSessionOnly(); //When PersistenceManagerFactoryBuilder.builder(session.getCluster()) .withEntities(Arrays.<Class<?>>asList(EntityWithNewSimpleField.class)).enableSchemaUpdate(true) .enableSchemaUpdateForTables(ImmutableMap.of("schema_dynamic_update.new_simple_field", false)) .relaxIndexValidation(false).build(); session.close(); } @Entity(keyspace = "schema_dynamic_update", table = "new_simple_field") public static class EntityWithNewSimpleField { @PartitionKey private Long id; @Column(name = "existing_field") private String existingField; private String unmappedField = "UNMAPPED"; @Column(name = "new_field") private String newField; @Column(name = "new_list") private List<String> newList; @Column(name = "new_set") private Set<String> newSet; @Column(name = "new_map") private Map<Integer, String> newMap; public EntityWithNewSimpleField() { } public EntityWithNewSimpleField(Long id, String existingField, String newField) { this.id = id; this.existingField = existingField; this.newField = newField; } public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getExistingField() { return existingField; } public void setExistingField(String existingField) { this.existingField = existingField; } public String getUnmappedField() { return unmappedField; } public void setUnmappedField(String unmappedField) { this.unmappedField = unmappedField; } public String getNewField() { return newField; } public void setNewField(String newField) { this.newField = newField; } public List<String> getNewList() { return newList; } public void setNewList(List<String> newList) { this.newList = newList; } public Set<String> getNewSet() { return newSet; } public void setNewSet(Set<String> newSet) { this.newSet = newSet; } public Map<Integer, String> getNewMap() { return newMap; } public void setNewMap(Map<Integer, String> newMap) { this.newMap = newMap; } } @Entity(keyspace = "schema_dynamic_update_counter", table = "new_counter_field") public static class ClusteredCounterEntityWithNewCounterField { @CompoundPrimaryKey private Compound id; @Column(name = "existing_counter") private Counter existingCounter; @Column(name = "new_counter_1") private Counter newCounter1; @Column(name = "new_counter_2") private Counter newCounter2; public ClusteredCounterEntityWithNewCounterField() { } public ClusteredCounterEntityWithNewCounterField(Long id, UUID date, Counter existingCounter) { this.id = new Compound(id, date); this.existingCounter = existingCounter; } public Compound getId() { return id; } public void setId(Compound id) { this.id = id; } public Counter getExistingCounter() { return existingCounter; } public void setExistingCounter(Counter existingCounter) { this.existingCounter = existingCounter; } public Counter getNewCounter1() { return newCounter1; } public void setNewCounter1(Counter newCounter1) { this.newCounter1 = newCounter1; } public Counter getNewCounter2() { return newCounter2; } public void setNewCounter2(Counter newCounter2) { this.newCounter2 = newCounter2; } public static class Compound { @PartitionKey private Long id; @ClusteringColumn @TimeUUID private UUID date; public Compound() { } public Compound(Long id, UUID date) { this.id = id; this.date = date; } public Long getId() { return id; } public void setId(Long id) { this.id = id; } public UUID getDate() { return date; } public void setDate(UUID date) { this.date = date; } } } @Entity(table = "entity_with_index") public static class EntityWithIndex { @PartitionKey private Long id; @Column private String name; public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } } }