diff --git a/src/main/java/com/avaje/ebean/annotation/Index.java b/src/main/java/com/avaje/ebean/annotation/Index.java index 2806293db..02c08e128 100644 --- a/src/main/java/com/avaje/ebean/annotation/Index.java +++ b/src/main/java/com/avaje/ebean/annotation/Index.java @@ -6,7 +6,7 @@ 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 */ @@ -27,6 +27,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 {}; diff --git a/src/main/java/com/avaje/ebean/annotation/Indices.java b/src/main/java/com/avaje/ebean/annotation/Indices.java new file mode 100644 index 000000000..2c119da70 --- /dev/null +++ b/src/main/java/com/avaje/ebean/annotation/Indices.java @@ -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[] indices() default {}; +} diff --git a/src/main/java/com/avaje/ebeaninternal/server/deploy/parse/AnnotationClass.java b/src/main/java/com/avaje/ebeaninternal/server/deploy/parse/AnnotationClass.java index 5b9b95da1..ebaed8e5b 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/deploy/parse/AnnotationClass.java +++ b/src/main/java/com/avaje/ebeaninternal/server/deploy/parse/AnnotationClass.java @@ -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; @@ -118,6 +119,13 @@ public class AnnotationClass extends AnnotationParser { descriptor.setName("Embeddable:" + cls.getSimpleName()); } + Indices indices = AnnotationBase.findAnnotation(cls, Indices.class); + if (indices != null) { + for (Index index: indices.indices()) { + 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())); diff --git a/src/main/java/com/avaje/ebeaninternal/server/deploy/parse/AnnotationFields.java b/src/main/java/com/avaje/ebeaninternal/server/deploy/parse/AnnotationFields.java index e1510dc78..e1328802b 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/deploy/parse/AnnotationFields.java +++ b/src/main/java/com/avaje/ebeaninternal/server/deploy/parse/AnnotationFields.java @@ -310,15 +310,46 @@ public class AnnotationFields extends AnnotationParser { } } + Indices indices = get(prop, Indices.class); + if (indices != null) { + for (Index index: indices.indices()) { + 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);