#368 - ENH: Enhance @Index to support multiple columns, unique flag and hence also be able to put on the class (annotation target TYPE)

This commit is contained in:
Robin Bygrave
2015-08-28 21:56:38 +12:00
parent 641ada001e
commit ccba5d08ef
14 changed files with 152 additions and 53 deletions
@@ -10,15 +10,24 @@ import java.lang.annotation.Target;
*
* @author rvbiljouw
*/
@Target({ElementType.FIELD})
@Target({ElementType.TYPE, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Index {
/**
* Name of the index
*
* @return index name
* Name of the index. If left blank a name is derived using the built in naming convention.
*/
String value() default "";
String name() default "";
/**
* If set true indicates this is a unique index.
*/
boolean unique() default false;
/**
* When placed on the class (rather than field) you can specify the columns
* to include in the index in order.
*/
String[] columnNames() default {};
}
@@ -324,14 +324,13 @@ public class BaseTableDdl implements TableDdl {
protected void writeCompoundUniqueConstraints(DdlBuffer apply, CreateTable createTable) throws IOException {
String tableName = createTable.getName();
List<UniqueConstraint> uniqueConstraints = createTable.getUniqueConstraint();
for (UniqueConstraint uniqueConstraint : uniqueConstraints) {
String uqName = uniqueConstraint.getName();
String[] columns = toColumnNamesSplit(uniqueConstraint.getColumnNames());
apply
.append(platformDdl.alterTableAddUniqueConstraint(tableName, uniqueConstraint.getName(), columns))
.endOfStatement();
apply.append(",").newLine();
apply.append(" constraint ").append(uqName).append(" unique");
appendColumns(columns, apply);
}
}
@@ -26,6 +26,17 @@ public class MIndex {
this.columns.add(columnName);
}
/**
* Create a multi column non unique index.
*/
public MIndex(String indexName, String tableName, String[] columnNames) {
this.tableName = tableName;
this.indexName = indexName;
for (int i = 0; i < columnNames.length; i++) {
this.columns.add(columnNames[i]);
}
}
public MIndex(CreateIndex createIndex) {
this.indexName = createIndex.getIndexName();
this.tableName = createIndex.getTableName();
@@ -9,6 +9,7 @@ import com.avaje.ebean.dbmigration.migration.DropColumn;
import com.avaje.ebean.dbmigration.migration.DropHistoryTable;
import com.avaje.ebean.dbmigration.migration.DropTable;
import com.avaje.ebean.dbmigration.migration.IdentityType;
import com.avaje.ebean.dbmigration.migration.UniqueConstraint;
import java.math.BigInteger;
import java.util.ArrayList;
@@ -169,6 +170,21 @@ public class MTable {
createTable.getForeignKey().add(compoundKey.createForeignKey());
}
for (MCompoundUniqueConstraint constraint : compoundUniqueConstraints) {
UniqueConstraint uq = new UniqueConstraint();
uq.setName(constraint.getName());
String[] columns = constraint.getColumns();
StringBuilder sb = new StringBuilder();
for (int i = 0; i < columns.length; i++) {
if (i > 0) {
sb.append(",");
}
sb.append(columns[i]);
}
uq.setColumnNames(sb.toString());
createTable.getUniqueConstraint().add(uq);
}
return createTable;
}
@@ -224,4 +224,12 @@ public class ModelContainer {
indexes.put(indexName, new MIndex(indexName, tableName, columnName));
}
/**
* Add a multi column index.
*/
public void addIndex(String indexName, String tableName, String[] columnNames) {
indexes.put(indexName, new MIndex(indexName, tableName, columnNames));
}
}
@@ -75,6 +75,10 @@ public class ModelBuildContext {
model.addIndex(indexName, tableName, columnName);
}
public void addIndex(String indexName, String tableName, String[] columnNames) {
model.addIndex(indexName, tableName, columnNames);
}
private String maxLength(String constraintName, int indexCount) {
return maxLength.maxLength(constraintName, indexCount);
}
@@ -9,7 +9,7 @@ import com.avaje.ebeaninternal.server.deploy.BeanProperty;
import com.avaje.ebeaninternal.server.deploy.BeanPropertyAssocMany;
import com.avaje.ebeaninternal.server.deploy.BeanPropertyAssocOne;
import com.avaje.ebeaninternal.server.deploy.BeanPropertyCompound;
import com.avaje.ebeaninternal.server.deploy.CompoundUniqueContraint;
import com.avaje.ebeaninternal.server.deploy.CompoundUniqueConstraint;
import com.avaje.ebeaninternal.server.deploy.TableJoinColumn;
import com.avaje.ebeaninternal.server.deploy.id.ImportedId;
@@ -36,24 +36,39 @@ public class ModelBuildPropertyVisitor extends BaseTablePropertyVisitor {
private int countCheck;
public ModelBuildPropertyVisitor(ModelBuildContext ctx, MTable table, CompoundUniqueContraint[] compoundUniqueConstraints) {
public ModelBuildPropertyVisitor(ModelBuildContext ctx, MTable table, CompoundUniqueConstraint[] constraints) {
this.ctx = ctx;
this.table = table;
addCompoundUniqueConstraint(compoundUniqueConstraints);
addCompoundUniqueConstraint(constraints);
}
/**
* Add unique constraints defined via JPA UniqueConstraint annotations.
*/
private void addCompoundUniqueConstraint(CompoundUniqueContraint[] compoundUniqueConstraints) {
private void addCompoundUniqueConstraint(CompoundUniqueConstraint[] constraints) {
if (compoundUniqueConstraints != null) {
for (int i = 0; i < compoundUniqueConstraints.length; i++) {
String[] columns = compoundUniqueConstraints[i].getColumns();
String uqName = determineUniqueConstraintName(columns);
table.addCompoundUniqueConstraint(columns, false, uqName);
if (constraints != null) {
for (int i = 0; i < constraints.length; i++) {
CompoundUniqueConstraint constraint = constraints[i];
String[] columns = constraint.getColumns();
indexSet.add(columns);
if (constraint.isUnique()) {
String uqName = constraint.getName();
if (uqName == null || uqName.trim().isEmpty()) {
uqName = determineUniqueConstraintName(columns);
}
table.addCompoundUniqueConstraint(columns, false, uqName);
} else {
// 'just' an index (not a unique constraint)
String idxName = constraint.getName();
if (idxName == null || idxName.trim().isEmpty()) {
idxName = determineIndexName(columns);
}
ctx.addIndex(idxName, table.getName(), columns);
}
}
}
}
@@ -133,7 +133,7 @@ public class BeanDescriptor<T> implements MetaBeanInfo, SpiBeanType<T> {
*/
private final ConcurrencyMode concurrencyMode;
private final CompoundUniqueContraint[] compoundUniqueConstraints;
private final CompoundUniqueConstraint[] compoundUniqueConstraints;
/**
* The base database table.
@@ -1352,7 +1352,7 @@ public class BeanDescriptor<T> implements MetaBeanInfo, SpiBeanType<T> {
@Override
public Object getBeanId(T bean) {
return getId((EntityBean)bean);
return getId((EntityBean) bean);
}
/**
@@ -1620,7 +1620,7 @@ public class BeanDescriptor<T> implements MetaBeanInfo, SpiBeanType<T> {
/**
* Return the compound unique constraints.
*/
public CompoundUniqueContraint[] getCompoundUniqueConstraints() {
public CompoundUniqueConstraint[] getCompoundUniqueConstraints() {
return compoundUniqueConstraints;
}
@@ -0,0 +1,50 @@
package com.avaje.ebeaninternal.server.deploy;
/**
* Holds multiple column unique constraints defined for an entity.
*/
public class CompoundUniqueConstraint {
private final String[] columns;
private final String name;
private final boolean unique;
public CompoundUniqueConstraint(String[] columns, String name, boolean unique) {
this.columns = columns;
this.unique = unique;
this.name = name;
}
/**
* Create a unique constraint given the column names.
*/
public CompoundUniqueConstraint(String[] columns) {
this.columns = columns;
this.unique = true;
this.name = null;
}
/**
* Return true if this is a unique constraint.
*/
public boolean isUnique() {
return unique;
}
/**
* Return the index name (can be null).
*/
public String getName() {
return name;
}
/**
* Return the columns that make up this unique constraint.
*/
public String[] getColumns() {
return columns;
}
}
@@ -1,21 +0,0 @@
package com.avaje.ebeaninternal.server.deploy;
/**
* Holds multiple column unique constraints defined for an entity.
*/
public class CompoundUniqueContraint {
private final String[] columns;
public CompoundUniqueContraint(String[] columns) {
this.columns = columns;
}
/**
* Return the columns that make up this unique constraint.
*/
public String[] getColumns() {
return columns;
}
}
@@ -16,7 +16,7 @@ import com.avaje.ebeaninternal.server.deploy.ChainedBeanPersistController;
import com.avaje.ebeaninternal.server.deploy.ChainedBeanPersistListener;
import com.avaje.ebeaninternal.server.deploy.ChainedBeanPostLoad;
import com.avaje.ebeaninternal.server.deploy.ChainedBeanQueryAdapter;
import com.avaje.ebeaninternal.server.deploy.CompoundUniqueContraint;
import com.avaje.ebeaninternal.server.deploy.CompoundUniqueConstraint;
import com.avaje.ebeaninternal.server.deploy.DRawSqlMeta;
import com.avaje.ebeaninternal.server.deploy.DeployNamedQuery;
import com.avaje.ebeaninternal.server.deploy.DeployNamedUpdate;
@@ -107,7 +107,7 @@ public class DeployBeanDescriptor<T> {
private boolean updateChangesOnly;
private List<CompoundUniqueContraint> compoundUniqueConstraints;
private List<CompoundUniqueConstraint> compoundUniqueConstraints;
/**
* The base database table.
@@ -371,9 +371,9 @@ public class DeployBeanDescriptor<T> {
/**
* Add a compound unique constraint.
*/
public void addCompoundUniqueConstraint(CompoundUniqueContraint c) {
public void addCompoundUniqueConstraint(CompoundUniqueConstraint c) {
if (compoundUniqueConstraints == null) {
compoundUniqueConstraints = new ArrayList<CompoundUniqueContraint>();
compoundUniqueConstraints = new ArrayList<CompoundUniqueConstraint>();
}
compoundUniqueConstraints.add(c);
}
@@ -381,11 +381,11 @@ public class DeployBeanDescriptor<T> {
/**
* Return the compound unique constraints (can be null).
*/
public CompoundUniqueContraint[] getCompoundUniqueConstraints() {
public CompoundUniqueConstraint[] getCompoundUniqueConstraints() {
if (compoundUniqueConstraints == null) {
return null;
} else {
return compoundUniqueConstraints.toArray(new CompoundUniqueContraint[compoundUniqueConstraints.size()]);
return compoundUniqueConstraints.toArray(new CompoundUniqueConstraint[compoundUniqueConstraints.size()]);
}
}
@@ -11,13 +11,14 @@ import com.avaje.ebean.annotation.CacheStrategy;
import com.avaje.ebean.annotation.CacheTuning;
import com.avaje.ebean.annotation.EntityConcurrencyMode;
import com.avaje.ebean.annotation.History;
import com.avaje.ebean.annotation.Index;
import com.avaje.ebean.annotation.NamedUpdate;
import com.avaje.ebean.annotation.NamedUpdates;
import com.avaje.ebean.annotation.UpdateMode;
import com.avaje.ebean.config.TableName;
import com.avaje.ebeaninternal.server.core.CacheOptions;
import com.avaje.ebeaninternal.server.deploy.BeanDescriptor.EntityType;
import com.avaje.ebeaninternal.server.deploy.CompoundUniqueContraint;
import com.avaje.ebeaninternal.server.deploy.CompoundUniqueConstraint;
import com.avaje.ebeaninternal.server.deploy.DeployNamedQuery;
import com.avaje.ebeaninternal.server.deploy.DeployNamedUpdate;
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanProperty;
@@ -76,9 +77,14 @@ public class AnnotationClass extends AnnotationParser {
descriptor.setName("Embeddable:" + cls.getSimpleName());
}
Index index = cls.getAnnotation(Index.class);
if (index != null) {
descriptor.addCompoundUniqueConstraint(new CompoundUniqueConstraint(index.columnNames(), index.name(), index.unique()));
}
UniqueConstraint uc = cls.getAnnotation(UniqueConstraint.class);
if (uc != null) {
descriptor.addCompoundUniqueConstraint(new CompoundUniqueContraint(uc.columnNames()));
descriptor.addCompoundUniqueConstraint(new CompoundUniqueConstraint(uc.columnNames()));
}
Table table = cls.getAnnotation(Table.class);
@@ -86,7 +92,7 @@ public class AnnotationClass extends AnnotationParser {
UniqueConstraint[] uniqueConstraints = table.uniqueConstraints();
if (uniqueConstraints != null) {
for (UniqueConstraint c : uniqueConstraints) {
descriptor.addCompoundUniqueConstraint(new CompoundUniqueContraint(c.columnNames()));
descriptor.addCompoundUniqueConstraint(new CompoundUniqueConstraint(c.columnNames()));
}
}
}
@@ -287,7 +287,7 @@ public class AnnotationFields extends AnnotationParser {
throw new RuntimeException("Can't use Index on foreign key relationships.");
}
prop.setIndexed();
prop.setIndexName(index.value());
prop.setIndexName(index.name());
}
}