mirror of
https://github.com/ebean-orm/ebean.git
synced 2026-10-24 06:12:43 +00:00
Merge pull request #814 from FOCONIS/master
ENHANCEMENT: multiple indices & meta-annotation support similar to spring-framework
This commit is contained in:
@@ -1,17 +1,19 @@
|
||||
package com.avaje.ebean.annotation;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Repeatable;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* An annotation for declaring an index on a single column.
|
||||
* An annotation for declaring an index.
|
||||
*
|
||||
* @author rvbiljouw
|
||||
*/
|
||||
@Target({ElementType.TYPE, ElementType.FIELD})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Repeatable(Indices.class)
|
||||
public @interface Index {
|
||||
|
||||
/**
|
||||
@@ -27,6 +29,9 @@ public @interface Index {
|
||||
/**
|
||||
* When placed on the class (rather than field) you can specify the columns
|
||||
* to include in the index in order.
|
||||
*
|
||||
* Wnen placed on a field, and columnNames are specified, the field-column has to be included.
|
||||
* You can use "${fa}" for alias
|
||||
*/
|
||||
String[] columnNames() default {};
|
||||
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.avaje.ebean.annotation;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
/**
|
||||
* An annotation for declaring multiple indices at class or field level.
|
||||
*
|
||||
* @author Roland Praml, FOCONIS AG
|
||||
*/
|
||||
@Target({ElementType.TYPE, ElementType.FIELD})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface Indices {
|
||||
|
||||
/**
|
||||
* Array with {@link Index} definitions.
|
||||
*/
|
||||
Index[] value() default {};
|
||||
}
|
||||
+2
-8
@@ -5,6 +5,7 @@ import com.avaje.ebean.annotation.ChangeLogInsertMode;
|
||||
import com.avaje.ebean.event.BeanPersistRequest;
|
||||
import com.avaje.ebean.event.changelog.ChangeLogFilter;
|
||||
import com.avaje.ebean.event.changelog.ChangeLogRegister;
|
||||
import com.avaje.ebeaninternal.server.deploy.parse.AnnotationBase;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
@@ -52,14 +53,7 @@ public class DefaultChangeLogRegister implements ChangeLogRegister {
|
||||
* Find and return the ChangeLog annotation in the inheritance hierarchy.
|
||||
*/
|
||||
private ChangeLog getChangeLog(Class<?> beanType) {
|
||||
ChangeLog changeLog = beanType.getAnnotation(ChangeLog.class);
|
||||
if (changeLog != null) {
|
||||
return changeLog;
|
||||
}
|
||||
if (Object.class.equals(beanType.getSuperclass())) {
|
||||
return null;
|
||||
}
|
||||
return getChangeLog(beanType.getSuperclass());
|
||||
return AnnotationBase.findAnnotation(beanType, ChangeLog.class);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -38,6 +38,7 @@ import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanPropertyAssocMany;
|
||||
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanPropertyAssocOne;
|
||||
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanTable;
|
||||
import com.avaje.ebeaninternal.server.deploy.meta.DeployTableJoin;
|
||||
import com.avaje.ebeaninternal.server.deploy.parse.AnnotationBase;
|
||||
import com.avaje.ebeaninternal.server.deploy.parse.DeployBeanInfo;
|
||||
import com.avaje.ebeaninternal.server.deploy.parse.DeployCreateProperties;
|
||||
import com.avaje.ebeaninternal.server.deploy.parse.DeployInherit;
|
||||
@@ -1457,7 +1458,7 @@ public class BeanDescriptorManager implements BeanDescriptorMap {
|
||||
* If so it is ok for it not to be enhanced.
|
||||
*/
|
||||
private boolean isMappedSuperWithNoProperties(Class<?> beanClass) {
|
||||
|
||||
// Attention: do not use AnnotationBase.findAnnotation(cls,...) here.
|
||||
MappedSuperclass annotation = beanClass.getAnnotation(MappedSuperclass.class);
|
||||
if (annotation == null) {
|
||||
return false;
|
||||
|
||||
@@ -18,6 +18,7 @@ import com.avaje.ebeaninternal.server.core.InternString;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanProperty;
|
||||
import com.avaje.ebeaninternal.server.deploy.DeployDocPropertyOptions;
|
||||
import com.avaje.ebeaninternal.server.deploy.generatedproperty.GeneratedProperty;
|
||||
import com.avaje.ebeaninternal.server.deploy.parse.AnnotationBase;
|
||||
import com.avaje.ebeaninternal.server.el.ElPropertyValue;
|
||||
import com.avaje.ebeaninternal.server.properties.BeanPropertyGetter;
|
||||
import com.avaje.ebeaninternal.server.properties.BeanPropertySetter;
|
||||
@@ -233,29 +234,29 @@ public class DeployBeanProperty {
|
||||
if (field == null) {
|
||||
return 0;
|
||||
}
|
||||
if (field.getAnnotation(Id.class) != null) {
|
||||
if (AnnotationBase.findAnnotation(field, Id.class) != null) {
|
||||
return ID_ORDER;
|
||||
} else if (field.getAnnotation(EmbeddedId.class) != null) {
|
||||
} else if (AnnotationBase.findAnnotation(field, EmbeddedId.class) != null) {
|
||||
return ID_ORDER;
|
||||
} else if (undirectionalShadow) {
|
||||
return UNIDIRECTIONAL_ORDER;
|
||||
} else if (isAuditProperty()) {
|
||||
return AUDITCOLUMN_ORDER;
|
||||
} else if (field.getAnnotation(Version.class) != null) {
|
||||
} else if (AnnotationBase.findAnnotation(field, Version.class) != null) {
|
||||
return VERSIONCOLUMN_ORDER;
|
||||
} else if (field.getAnnotation(SoftDelete.class) != null) {
|
||||
} else if (AnnotationBase.findAnnotation(field, SoftDelete.class) != null) {
|
||||
return VERSIONCOLUMN_ORDER;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
private boolean isAuditProperty() {
|
||||
return (field.getAnnotation(WhenCreated.class) != null
|
||||
|| field.getAnnotation(WhenModified.class) != null
|
||||
|| field.getAnnotation(WhoModified.class) != null
|
||||
|| field.getAnnotation(WhoCreated.class) != null
|
||||
|| field.getAnnotation(UpdatedTimestamp.class) != null
|
||||
|| field.getAnnotation(CreatedTimestamp.class) != null);
|
||||
return (AnnotationBase.findAnnotation(field, WhenCreated.class) != null
|
||||
|| AnnotationBase.findAnnotation(field, WhenModified.class) != null
|
||||
|| AnnotationBase.findAnnotation(field, WhoModified.class) != null
|
||||
|| AnnotationBase.findAnnotation(field, WhoCreated.class) != null
|
||||
|| AnnotationBase.findAnnotation(field, UpdatedTimestamp.class) != null
|
||||
|| AnnotationBase.findAnnotation(field, CreatedTimestamp.class) != null);
|
||||
}
|
||||
|
||||
public String getFullBeanName() {
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
package com.avaje.ebeaninternal.server.deploy.parse;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.AnnotatedElement;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import com.avaje.ebean.config.NamingConvention;
|
||||
import com.avaje.ebean.config.dbplatform.DatabasePlatform;
|
||||
@@ -46,12 +49,12 @@ public abstract class AnnotationBase {
|
||||
T a = null;
|
||||
Field field = prop.getField();
|
||||
if (field != null) {
|
||||
a = field.getAnnotation(annClass);
|
||||
a = findAnnotation(field, annClass);
|
||||
}
|
||||
if (a == null) {
|
||||
Method m = prop.getReadMethod();
|
||||
if (m != null) {
|
||||
a = m.getAnnotation(annClass);
|
||||
a = findAnnotation(m, annClass);
|
||||
}
|
||||
}
|
||||
return a;
|
||||
@@ -66,10 +69,95 @@ public abstract class AnnotationBase {
|
||||
protected <T extends Annotation> T find(DeployBeanProperty prop, Class<T> annClass) {
|
||||
T a = get(prop, annClass);
|
||||
if (a == null) {
|
||||
a = prop.getOwningType().getAnnotation(annClass);
|
||||
a = findAnnotation(prop.getOwningType(),annClass);
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
|
||||
// this code is taken from the spring framework to find annotations recursively
|
||||
|
||||
/**
|
||||
* Determine if the supplied {@link Annotation} is defined in the core JDK
|
||||
* {@code java.lang.annotation} package.
|
||||
*/
|
||||
public static boolean isInJavaLangAnnotationPackage(Annotation annotation) {
|
||||
return annotation.annotationType().getName().startsWith("java.lang.annotation");
|
||||
}
|
||||
|
||||
/**
|
||||
* Find a single {@link Annotation} of {@code annotationType} on the
|
||||
* supplied {@link AnnotatedElement}.
|
||||
* <p>Meta-annotations will be searched if the annotation is not
|
||||
* <em>directly present</em> on the supplied element.
|
||||
* <p><strong>Warning</strong>: this method operates generically on
|
||||
* annotated elements. In other words, this method does not execute
|
||||
* specialized search algorithms for classes or methods. It only
|
||||
* traverses through Annotations!</p>
|
||||
*/
|
||||
public static <A extends Annotation> A findAnnotation(AnnotatedElement annotatedElement, Class<A> annotationType) {
|
||||
if (annotationType == null) {
|
||||
return null;
|
||||
}
|
||||
// check if directly present, if not, start recursive traversal
|
||||
A ann = annotatedElement.getAnnotation(annotationType);
|
||||
if (ann != null) {
|
||||
return ann;
|
||||
} else {
|
||||
return findAnnotation(annotatedElement, annotationType, new HashSet<Annotation>());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Find a single {@link Annotation} of {@code annotationType} on the
|
||||
* supplied {@link clazz}.
|
||||
* <p>Meta-annotations will be searched if the annotation is not
|
||||
* <em>directly present</em> on the supplied element.
|
||||
* <p><strong>Note</strong>: this method searches for annotations at
|
||||
* class & superClass(es)!</p>
|
||||
*/
|
||||
public static <A extends Annotation> A findAnnotation(Class<?> clazz, Class<A> annotationType) {
|
||||
if (annotationType == null) {
|
||||
return null;
|
||||
}
|
||||
// check if directly present, if not, start recursive traversal
|
||||
A ann = clazz.getAnnotation(annotationType);
|
||||
if (ann != null) {
|
||||
return ann;
|
||||
} else {
|
||||
while (clazz != null && clazz != Object.class) {
|
||||
ann = findAnnotation(clazz, annotationType, new HashSet<Annotation>());
|
||||
if (ann != null) {
|
||||
return ann;
|
||||
}
|
||||
// not present at this class - traverse to superclass
|
||||
clazz = clazz.getSuperclass();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Perform the search algorithm for {@link #findAnnotation(AnnotatedElement, Class)}
|
||||
* avoiding endless recursion by tracking which annotations have already
|
||||
* been <em>visited</em>.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
private static <A extends Annotation> A findAnnotation(AnnotatedElement annotatedElement, Class<A> annotationType, Set<Annotation> visited) {
|
||||
|
||||
Annotation[] anns = annotatedElement.getDeclaredAnnotations();
|
||||
for (Annotation ann : anns) {
|
||||
if (ann.annotationType() == annotationType) {
|
||||
return (A) ann;
|
||||
}
|
||||
}
|
||||
for (Annotation ann : anns) {
|
||||
if (!isInJavaLangAnnotationPackage(ann) && visited.add(ann)) {
|
||||
A annotation = findAnnotation((AnnotatedElement) ann.annotationType(), annotationType, visited);
|
||||
if (annotation != null) {
|
||||
return annotation;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import com.avaje.ebean.annotation.Draftable;
|
||||
import com.avaje.ebean.annotation.DraftableElement;
|
||||
import com.avaje.ebean.annotation.History;
|
||||
import com.avaje.ebean.annotation.Index;
|
||||
import com.avaje.ebean.annotation.Indices;
|
||||
import com.avaje.ebean.annotation.ReadAudit;
|
||||
import com.avaje.ebean.annotation.UpdateMode;
|
||||
import com.avaje.ebean.annotation.View;
|
||||
@@ -66,7 +67,7 @@ public class AnnotationClass extends AnnotationParser {
|
||||
public void parseAttributeOverride() {
|
||||
|
||||
Class<?> cls = descriptor.getBeanType();
|
||||
AttributeOverride override = cls.getAnnotation(AttributeOverride.class);
|
||||
AttributeOverride override = AnnotationBase.findAnnotation(cls,AttributeOverride.class);
|
||||
if (override != null) {
|
||||
String propertyName = override.name();
|
||||
Column column = override.column();
|
||||
@@ -103,7 +104,7 @@ public class AnnotationClass extends AnnotationParser {
|
||||
|
||||
private void read(Class<?> cls) {
|
||||
|
||||
Entity entity = cls.getAnnotation(Entity.class);
|
||||
Entity entity = AnnotationBase.findAnnotation(cls,Entity.class);
|
||||
if (entity != null) {
|
||||
if (entity.name().equals("")) {
|
||||
descriptor.setName(cls.getSimpleName());
|
||||
@@ -112,27 +113,34 @@ public class AnnotationClass extends AnnotationParser {
|
||||
}
|
||||
}
|
||||
|
||||
Embeddable embeddable = cls.getAnnotation(Embeddable.class);
|
||||
Embeddable embeddable = AnnotationBase.findAnnotation(cls,Embeddable.class);
|
||||
if (embeddable != null) {
|
||||
descriptor.setEntityType(EntityType.EMBEDDED);
|
||||
descriptor.setName("Embeddable:" + cls.getSimpleName());
|
||||
}
|
||||
|
||||
Index index = cls.getAnnotation(Index.class);
|
||||
Indices indices = AnnotationBase.findAnnotation(cls, Indices.class);
|
||||
if (indices != null) {
|
||||
for (Index index: indices.value()) {
|
||||
descriptor.addIndex(new IndexDefinition(index.columnNames(), index.name(), index.unique()));
|
||||
}
|
||||
}
|
||||
|
||||
Index index = AnnotationBase.findAnnotation(cls,Index.class);
|
||||
if (index != null) {
|
||||
descriptor.addIndex(new IndexDefinition(index.columnNames(), index.name(), index.unique()));
|
||||
}
|
||||
|
||||
UniqueConstraint uc = cls.getAnnotation(UniqueConstraint.class);
|
||||
UniqueConstraint uc = AnnotationBase.findAnnotation(cls,UniqueConstraint.class);
|
||||
if (uc != null) {
|
||||
descriptor.addIndex(new IndexDefinition(uc.columnNames()));
|
||||
}
|
||||
|
||||
View view = cls.getAnnotation(View.class);
|
||||
View view = AnnotationBase.findAnnotation(cls,View.class);
|
||||
if (view != null) {
|
||||
descriptor.setView(view.name(), view.dependentTables());
|
||||
}
|
||||
Table table = cls.getAnnotation(Table.class);
|
||||
Table table = AnnotationBase.findAnnotation(cls,Table.class);
|
||||
if (table != null) {
|
||||
UniqueConstraint[] uniqueConstraints = table.uniqueConstraints();
|
||||
for (UniqueConstraint c : uniqueConstraints) {
|
||||
@@ -140,54 +148,54 @@ public class AnnotationClass extends AnnotationParser {
|
||||
}
|
||||
}
|
||||
|
||||
Draftable draftable = cls.getAnnotation(Draftable.class);
|
||||
Draftable draftable = AnnotationBase.findAnnotation(cls,Draftable.class);
|
||||
if (draftable != null) {
|
||||
descriptor.setDraftable();
|
||||
}
|
||||
|
||||
DraftableElement draftableElement = cls.getAnnotation(DraftableElement.class);
|
||||
DraftableElement draftableElement = AnnotationBase.findAnnotation(cls,DraftableElement.class);
|
||||
if (draftableElement != null) {
|
||||
descriptor.setDraftableElement();
|
||||
}
|
||||
|
||||
ReadAudit readAudit = cls.getAnnotation(ReadAudit.class);
|
||||
ReadAudit readAudit = AnnotationBase.findAnnotation(cls,ReadAudit.class);
|
||||
if (readAudit != null) {
|
||||
descriptor.setReadAuditing();
|
||||
}
|
||||
|
||||
History history = cls.getAnnotation(History.class);
|
||||
History history = AnnotationBase.findAnnotation(cls,History.class);
|
||||
if (history != null) {
|
||||
descriptor.setHistorySupport();
|
||||
}
|
||||
|
||||
DbComment comment = cls.getAnnotation(DbComment.class);
|
||||
DbComment comment = AnnotationBase.findAnnotation(cls,DbComment.class);
|
||||
if (comment != null) {
|
||||
descriptor.setDbComment(comment.value());
|
||||
}
|
||||
|
||||
DocStore docStore = cls.getAnnotation(DocStore.class);
|
||||
DocStore docStore = AnnotationBase.findAnnotation(cls,DocStore.class);
|
||||
if (docStore != null) {
|
||||
descriptor.readDocStore(docStore);
|
||||
}
|
||||
|
||||
UpdateMode updateMode = cls.getAnnotation(UpdateMode.class);
|
||||
UpdateMode updateMode = AnnotationBase.findAnnotation(cls,UpdateMode.class);
|
||||
if (updateMode != null) {
|
||||
descriptor.setUpdateChangesOnly(updateMode.updateChangesOnly());
|
||||
}
|
||||
|
||||
Cache cache = cls.getAnnotation(Cache.class);
|
||||
Cache cache = AnnotationBase.findAnnotation(cls,Cache.class);
|
||||
if (cache != null && !disableL2Cache) {
|
||||
descriptor.setCache(cache);
|
||||
}
|
||||
|
||||
NamedQueries namedQueries = cls.getAnnotation(NamedQueries.class);
|
||||
NamedQueries namedQueries = AnnotationBase.findAnnotation(cls,NamedQueries.class);
|
||||
if (namedQueries != null) {
|
||||
for (NamedQuery namedQuery : namedQueries.value()) {
|
||||
descriptor.addNamedQuery(namedQuery.name(), namedQuery.query());
|
||||
}
|
||||
}
|
||||
|
||||
NamedQuery namedQuery = cls.getAnnotation(NamedQuery.class);
|
||||
NamedQuery namedQuery = AnnotationBase.findAnnotation(cls,NamedQuery.class);
|
||||
if (namedQuery != null) {
|
||||
descriptor.addNamedQuery(namedQuery.name(), namedQuery.query());
|
||||
}
|
||||
|
||||
@@ -310,15 +310,46 @@ public class AnnotationFields extends AnnotationParser {
|
||||
}
|
||||
}
|
||||
|
||||
Indices indices = get(prop, Indices.class);
|
||||
if (indices != null) {
|
||||
for (Index index: indices.value()) {
|
||||
addIndex(prop, index);
|
||||
}
|
||||
}
|
||||
|
||||
Index index = get(prop, Index.class);
|
||||
if (index != null) {
|
||||
if (hasRelationshipItem(prop)) {
|
||||
throw new RuntimeException("Can't use Index on foreign key relationships.");
|
||||
}
|
||||
descriptor.addIndex(new IndexDefinition(prop.getDbColumn(), index.name(), index.unique()));
|
||||
addIndex(prop, index);
|
||||
}
|
||||
}
|
||||
|
||||
private void addIndex(DeployBeanProperty prop, Index index) {
|
||||
String[] columnNames;
|
||||
if (index.columnNames() == null || index.columnNames().length == 0) {
|
||||
columnNames = new String[] {prop.getDbColumn()};
|
||||
} else {
|
||||
columnNames = new String[index.columnNames().length];
|
||||
int i=0;
|
||||
int found = 0;
|
||||
for (String colName : index.columnNames()) {
|
||||
if (colName.equals("${fa}") || colName.equals(prop.getDbColumn())) {
|
||||
columnNames[i++] = prop.getDbColumn();
|
||||
found++;
|
||||
} else {
|
||||
columnNames[i++] = colName;
|
||||
}
|
||||
}
|
||||
if (found != 1) {
|
||||
throw new RuntimeException("DB-columname has to be specified exactly one time in columnNames.");
|
||||
}
|
||||
}
|
||||
|
||||
if (columnNames.length == 1 && hasRelationshipItem(prop)) {
|
||||
throw new RuntimeException("Can't use Index on foreign key relationships.");
|
||||
}
|
||||
descriptor.addIndex(new IndexDefinition(columnNames, index.name(), index.unique()));
|
||||
}
|
||||
|
||||
private void readJsonAnnotations(DeployBeanProperty prop) {
|
||||
if (jacksonAnnotationsPresent) {
|
||||
com.fasterxml.jackson.annotation.JsonIgnore jsonIgnore = get(prop, com.fasterxml.jackson.annotation.JsonIgnore.class);
|
||||
|
||||
@@ -14,7 +14,7 @@ public class AnnotationSql extends AnnotationParser {
|
||||
|
||||
public void parse() {
|
||||
Class<?> cls = descriptor.getBeanType();
|
||||
Sql sql = cls.getAnnotation(Sql.class);
|
||||
Sql sql = AnnotationBase.findAnnotation(cls,Sql.class);
|
||||
if (sql != null) {
|
||||
descriptor.setEntityType(BeanDescriptor.EntityType.SQL);
|
||||
}
|
||||
|
||||
+7
-7
@@ -223,7 +223,7 @@ public class DeployCreateProperties {
|
||||
|
||||
Class<?> propertyType = field.getType();
|
||||
|
||||
ManyToOne manyToOne = field.getAnnotation(ManyToOne.class);
|
||||
ManyToOne manyToOne = AnnotationBase.findAnnotation(field,ManyToOne.class);
|
||||
if (manyToOne != null){
|
||||
Class<?> tt = manyToOne.targetEntity();
|
||||
if (!tt.equals(void.class)){
|
||||
@@ -240,7 +240,7 @@ public class DeployCreateProperties {
|
||||
// List, Set or Map based object
|
||||
Class<?> targetType = determineTargetType(field);
|
||||
if (targetType == null) {
|
||||
Transient transAnnotation = field.getAnnotation(Transient.class);
|
||||
Transient transAnnotation = AnnotationBase.findAnnotation(field,Transient.class);
|
||||
if (transAnnotation != null) {
|
||||
// not supporting this field (generic type used)
|
||||
return null;
|
||||
@@ -298,15 +298,15 @@ public class DeployCreateProperties {
|
||||
* Return true if the field has one of the special mappings.
|
||||
*/
|
||||
private boolean isSpecialScalarType(Field field) {
|
||||
return (field.getAnnotation(DbJson.class) != null)
|
||||
|| (field.getAnnotation(DbJsonB.class) != null)
|
||||
|| (field.getAnnotation(DbArray.class) != null)
|
||||
|| (field.getAnnotation(DbHstore.class) != null);
|
||||
return (AnnotationBase.findAnnotation(field,DbJson.class) != null)
|
||||
|| (AnnotationBase.findAnnotation(field,DbJsonB.class) != null)
|
||||
|| (AnnotationBase.findAnnotation(field,DbArray.class) != null)
|
||||
|| (AnnotationBase.findAnnotation(field,DbHstore.class) != null);
|
||||
}
|
||||
|
||||
private boolean isTransientField(Field field) {
|
||||
|
||||
Transient t = field.getAnnotation(Transient.class);
|
||||
Transient t = AnnotationBase.findAnnotation(field,Transient.class);
|
||||
return (t != null);
|
||||
}
|
||||
|
||||
|
||||
@@ -111,11 +111,11 @@ public class DeployInherit {
|
||||
info.setParent(parent);
|
||||
}
|
||||
|
||||
Inheritance ia = cls.getAnnotation(Inheritance.class);
|
||||
Inheritance ia = AnnotationBase.findAnnotation(cls,Inheritance.class);
|
||||
if (ia != null) {
|
||||
ia.strategy();
|
||||
}
|
||||
DiscriminatorColumn da = cls.getAnnotation(DiscriminatorColumn.class);
|
||||
DiscriminatorColumn da = AnnotationBase.findAnnotation(cls,DiscriminatorColumn.class);
|
||||
if (da != null) {
|
||||
// lowercase the discriminator column for RawSql and JSON
|
||||
info.setDiscriminatorColumn(da.name().toLowerCase());
|
||||
@@ -128,7 +128,7 @@ public class DeployInherit {
|
||||
info.setDiscriminatorLength(da.length());
|
||||
}
|
||||
|
||||
DiscriminatorValue dv = cls.getAnnotation(DiscriminatorValue.class);
|
||||
DiscriminatorValue dv = AnnotationBase.findAnnotation(cls,DiscriminatorValue.class);
|
||||
if (dv != null) {
|
||||
info.setDiscriminatorValue(dv.value());
|
||||
}
|
||||
@@ -149,7 +149,7 @@ public class DeployInherit {
|
||||
if (cls.equals(Object.class)) {
|
||||
return false;
|
||||
}
|
||||
Annotation a = cls.getAnnotation(Inheritance.class);
|
||||
Annotation a = AnnotationBase.findAnnotation(cls,Inheritance.class);
|
||||
if (a != null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
package com.avaje.tests.basic;
|
||||
|
||||
import javax.persistence.PersistenceException;
|
||||
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.avaje.ebean.BaseTestCase;
|
||||
import com.avaje.ebean.Ebean;
|
||||
import com.avaje.tests.model.basic.Address;
|
||||
import com.avaje.tests.model.basic.metaannotation.SizeMedium;
|
||||
/**
|
||||
* Very simple test case to check if Ebean recognizes meta-annotation correctly.
|
||||
*
|
||||
* @author Roland Praml, FOCONIS AG
|
||||
*/
|
||||
public class TestMetaAnnotation extends BaseTestCase {
|
||||
private static final String spaces100 = new String(new char[100]).replace('\0', ' ');
|
||||
private static final String spaces101 = new String(new char[101]).replace('\0', ' ');
|
||||
|
||||
/**
|
||||
* This test writes 100 spaces to "line1" which is annotated with @Size(max=100)
|
||||
*/
|
||||
@Test
|
||||
public void testWrite100SpacesToLine1() {
|
||||
Ebean.createUpdate(Address.class, "delete from address");
|
||||
|
||||
Address address = new Address();
|
||||
address.setLine1(spaces100);
|
||||
Ebean.save(address);
|
||||
}
|
||||
|
||||
/**
|
||||
* This test writes 101 spaces to "line1" which is annotated with @Size(max=100).
|
||||
*/
|
||||
@Test(expected=PersistenceException.class)
|
||||
@Ignore // Unfortunately, this test does not work with PostGres as DB-Backend, as it does not honor the @Size annotation
|
||||
public void testWrite101SpacesToLine1() {
|
||||
Ebean.createUpdate(Address.class, "delete from address");
|
||||
|
||||
Address address = new Address();
|
||||
address.setLine1(spaces101);
|
||||
Ebean.save(address);
|
||||
}
|
||||
|
||||
/**
|
||||
* This test writes 100 spaces to "line1" which is meta-annotated with {@link SizeMedium}.
|
||||
*/
|
||||
@Test
|
||||
public void testWrite100SpacesToLine2() {
|
||||
Ebean.createUpdate(Address.class, "delete from address");
|
||||
|
||||
Address address = new Address();
|
||||
address.setLine2(spaces100);
|
||||
Ebean.save(address);
|
||||
}
|
||||
|
||||
/**
|
||||
* This test writes 101 spaces to "line1" which is meta-annotated with {@link SizeMedium}.
|
||||
*/
|
||||
@Test(expected=PersistenceException.class)
|
||||
@Ignore // Unfortunately, this test does not work with PostGres as Backend
|
||||
public void testWrite101SpacesToLine2() {
|
||||
Ebean.createUpdate(Address.class, "delete from address");
|
||||
|
||||
Address address = new Address();
|
||||
address.setLine2(spaces101);
|
||||
Ebean.save(address);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -7,6 +7,9 @@ import javax.persistence.ManyToOne;
|
||||
import javax.persistence.Table;
|
||||
import javax.persistence.Version;
|
||||
import javax.validation.constraints.Size;
|
||||
|
||||
import com.avaje.tests.model.basic.metaannotation.SizeMedium;
|
||||
|
||||
import java.sql.Timestamp;
|
||||
|
||||
/**
|
||||
@@ -23,11 +26,11 @@ public class Address {
|
||||
@Column(name = "line_1")
|
||||
String line1;
|
||||
|
||||
@Size(max = 100)
|
||||
@SizeMedium
|
||||
@Column(name = "line_2")
|
||||
String line2;
|
||||
|
||||
@Size(max = 100)
|
||||
@SizeMedium
|
||||
String city;
|
||||
|
||||
Timestamp cretime;
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.avaje.tests.model.basic.metaannotation;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import javax.validation.constraints.Size;
|
||||
|
||||
/**
|
||||
* Meta-Annotation that defines @Size(max=100)
|
||||
* @author Roland Praml, FOCONIS AG
|
||||
*/
|
||||
@Target(ElementType.FIELD)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
@Size(max=100)
|
||||
public @interface SizeMedium {
|
||||
}
|
||||
Reference in New Issue
Block a user