Cache data from MaterializedViews under their parent name. Add some relationship constraints that can decorate getters in model classes and be used in some cases to better cache data.

This commit is contained in:
Greg Burd 2017-11-06 13:49:34 -05:00
parent fe47531984
commit a79e7dacf1
12 changed files with 337 additions and 9 deletions

View file

@ -45,6 +45,7 @@ public class CacheUtil {
}
public static Object merge(Object to, Object from) {
// TODO(gburd): do a proper merge given that materialized views are cached with their table name
if (to == from) {
return to;
} else {

View file

@ -156,6 +156,8 @@ public final class InsertOperation<T> extends AbstractOperation<T, InsertOperati
insert.value(t._1.getColumnName(), t._2);
});
//TODO(gburd): IF NOT EXISTS when @Constraints.Relationship is 1:1 or 1:m
if (this.ttl != null) {
insert.using(QueryBuilder.ttl(this.ttl[0]));
}

View file

@ -114,7 +114,13 @@ public final class HelenusMappingEntity implements HelenusEntity {
List<HelenusProperty> primaryKeyProperties = new ArrayList<>();
ImmutableList.Builder<Facet> facetsBuilder = ImmutableList.builder();
facetsBuilder.add(new Facet("table", name.toCql()).setFixed());
if (iface.getDeclaredAnnotation(MaterializedView.class) == null) {
facetsBuilder.add(new Facet("table", name.toCql()).setFixed());
} else {
facetsBuilder.add(
new Facet("table", Helenus.entity(iface.getInterfaces()[0]).getName().toCql())
.setFixed());
}
for (HelenusProperty prop : orderedProps) {
switch (prop.getColumnType()) {
case PARTITION_KEY:
@ -130,7 +136,7 @@ public final class HelenusMappingEntity implements HelenusEntity {
MappingUtil.getValidators(prop.getGetterMethod())) {
if (constraint.getClass().isAssignableFrom(DistinctValidator.class)) {
DistinctValidator validator = (DistinctValidator) constraint;
String[] values = validator.value();
String[] values = validator.constraintAnnotation.value();
UnboundFacet facet;
if (values != null && values.length >= 1 && !(StringUtils.isBlank(values[0]))) {
List<HelenusProperty> props = new ArrayList<HelenusProperty>(values.length + 1);

View file

@ -235,4 +235,96 @@ public final class Constraints {
*/
String[] value() default "";
}
/**
* Distinct annotation is used to signal, but not ensure that a value should be distinct in the
* database.
*
* <p>Can be used only for @java.lang.CharSequence
*
* <p>It does not have effect on selects and data retrieval operations
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(value = {ElementType.METHOD, ElementType.ANNOTATION_TYPE})
@Constraint(validatedBy = OneToOneRelationshipValidator.class)
public @interface OneToOne {
/**
* User defined list of properties that combine with this one to result in a distinct
* combination in the table.
*
* @return Java
*/
String[] value() default "";
}
/**
* Distinct annotation is used to signal, but not ensure that a value should be distinct in the
* database.
*
* <p>Can be used only for @java.lang.CharSequence
*
* <p>It does not have effect on selects and data retrieval operations
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(value = {ElementType.METHOD, ElementType.ANNOTATION_TYPE})
@Constraint(validatedBy = OneToManyRelationshipValidator.class)
public @interface OneToMany {
/**
* User defined list of properties that combine with this one to result in a distinct
* combination in the table.
*
* @return Java
*/
String[] value() default "";
}
/**
* Distinct annotation is used to signal, but not ensure that a value should be distinct in the
* database.
*
* <p>Can be used only for @java.lang.CharSequence
*
* <p>It does not have effect on selects and data retrieval operations
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(value = {ElementType.METHOD, ElementType.ANNOTATION_TYPE})
@Constraint(validatedBy = ManyToOneRelationshipValidator.class)
public @interface ManyToOne {
/**
* User defined list of properties that combine with this one to result in a distinct
* combination in the table.
*
* @return Java
*/
String[] value() default "";
}
/**
* Distinct annotation is used to signal, but not ensure that a value should be distinct in the
* database.
*
* <p>Can be used only for @java.lang.CharSequence
*
* <p>It does not have effect on selects and data retrieval operations
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(value = {ElementType.METHOD, ElementType.ANNOTATION_TYPE})
@Constraint(validatedBy = ManyToManyRelationshipValidator.class)
public @interface ManyToMany {
/**
* User defined list of properties that combine with this one to result in a distinct
* combination in the table.
*
* @return Java
*/
String[] value() default "";
}
}

View file

@ -0,0 +1,34 @@
/*
* Copyright (C) 2015 The Helenus Authors
*
* 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 net.helenus.mapping.validator;
import java.lang.annotation.Annotation;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
public abstract class AbstractConstraintValidator<A extends Annotation, T>
implements ConstraintValidator<A, T> {
public A constraintAnnotation;
@Override
public void initialize(A constraintAnnotation) {
this.constraintAnnotation = constraintAnnotation;
}
@Override
public abstract boolean isValid(T value, ConstraintValidatorContext context);
}

View file

@ -20,13 +20,12 @@ import javax.validation.ConstraintValidatorContext;
import net.helenus.mapping.annotation.Constraints;
public final class DistinctValidator
extends AbstractConstraintValidator<Constraints.Distinct, CharSequence>
implements ConstraintValidator<Constraints.Distinct, CharSequence> {
private Constraints.Distinct annotation;
@Override
public void initialize(Constraints.Distinct constraintAnnotation) {
annotation = constraintAnnotation;
super.initialize(constraintAnnotation);
}
@Override
@ -34,8 +33,4 @@ public final class DistinctValidator
// TODO(gburd): check that the list contains valid property names.
return true;
}
public String[] value() {
return annotation == null ? null : annotation.value();
}
}

View file

@ -0,0 +1,33 @@
/*
* Copyright (C) 2015 The Helenus Authors
*
* 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 net.helenus.mapping.validator;
import javax.validation.ConstraintValidatorContext;
import net.helenus.mapping.annotation.Constraints;
public class ManyToManyRelationshipValidator extends RelationshipValidator<Constraints.ManyToMany> {
@Override
public void initialize(Constraints.ManyToMany constraintAnnotation) {
super.initialize(constraintAnnotation);
}
@Override
public boolean isValid(CharSequence value, ConstraintValidatorContext context) {
// TODO(gburd): check that the list contains valid property names.
return true;
}
}

View file

@ -0,0 +1,33 @@
/*
* Copyright (C) 2015 The Helenus Authors
*
* 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 net.helenus.mapping.validator;
import javax.validation.ConstraintValidatorContext;
import net.helenus.mapping.annotation.Constraints;
public class ManyToOneRelationshipValidator extends RelationshipValidator<Constraints.ManyToOne> {
@Override
public void initialize(Constraints.ManyToOne constraintAnnotation) {
super.initialize(constraintAnnotation);
}
@Override
public boolean isValid(CharSequence value, ConstraintValidatorContext context) {
// TODO(gburd): check that the list contains valid property names.
return true;
}
}

View file

@ -0,0 +1,33 @@
/*
* Copyright (C) 2015 The Helenus Authors
*
* 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 net.helenus.mapping.validator;
import javax.validation.ConstraintValidatorContext;
import net.helenus.mapping.annotation.Constraints;
public class OneToManyRelationshipValidator extends RelationshipValidator<Constraints.OneToMany> {
@Override
public void initialize(Constraints.OneToMany constraintAnnotation) {
super.initialize(constraintAnnotation);
}
@Override
public boolean isValid(CharSequence value, ConstraintValidatorContext context) {
// TODO(gburd): check that the list contains valid property names.
return true;
}
}

View file

@ -0,0 +1,33 @@
/*
* Copyright (C) 2015 The Helenus Authors
*
* 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 net.helenus.mapping.validator;
import javax.validation.ConstraintValidatorContext;
import net.helenus.mapping.annotation.Constraints;
public class OneToOneRelationshipValidator extends RelationshipValidator<Constraints.OneToOne> {
@Override
public void initialize(Constraints.OneToOne constraintAnnotation) {
super.initialize(constraintAnnotation);
}
@Override
public boolean isValid(CharSequence value, ConstraintValidatorContext context) {
// TODO(gburd): check that the list contains valid property names.
return true;
}
}

View file

@ -0,0 +1,35 @@
/*
* Copyright (C) 2015 The Helenus Authors
*
* 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 net.helenus.mapping.validator;
import java.lang.annotation.Annotation;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
public abstract class RelationshipValidator<A extends Annotation>
extends AbstractConstraintValidator<A, CharSequence>
implements ConstraintValidator<A, CharSequence> {
@Override
public void initialize(A constraintAnnotation) {
super.initialize(constraintAnnotation);
}
@Override
public boolean isValid(CharSequence value, ConstraintValidatorContext context) {
return false;
}
}

View file

@ -22,9 +22,12 @@ import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.UUID;
import java.util.concurrent.TimeoutException;
import net.helenus.core.ConflictingUnitOfWorkException;
import net.helenus.core.Helenus;
import net.helenus.core.HelenusSession;
import net.helenus.core.UnitOfWork;
import net.helenus.test.integration.build.AbstractEmbeddedCassandraTest;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
@ -78,6 +81,34 @@ public class MaterializedViewTest extends AbstractEmbeddedCassandraTest {
.from(CyclistsByAge.class)
.where(cyclist::age, eq(18))
.allowFiltering()
.single()
.sync();
}
@Test
public void testMvUnitOfWork()
throws TimeoutException, ConflictingUnitOfWorkException, Exception {
Cyclist c1, c2;
UnitOfWork uow = session.begin();
c1 =
session
.<Cyclist>select(Cyclist.class)
.from(CyclistsByAge.class)
.where(cyclist::age, eq(18))
.single()
.sync(uow)
.orElse(null);
c2 =
session
.<Cyclist>select(Cyclist.class)
.from(CyclistsByAge.class)
.where(cyclist::age, eq(18))
.single()
.sync(uow)
.orElse(null);
Assert.assertEquals(c1, c2);
uow.commit();
}
}