diff --git a/hibernate-core/src/main/java/org/hibernate/cfg/AnnotationBinder.java b/hibernate-core/src/main/java/org/hibernate/cfg/AnnotationBinder.java index bbea1b6e98..fb7fa288e7 100644 --- a/hibernate-core/src/main/java/org/hibernate/cfg/AnnotationBinder.java +++ b/hibernate-core/src/main/java/org/hibernate/cfg/AnnotationBinder.java @@ -2172,7 +2172,6 @@ public final class AnnotationBinder { JoinColumn[] annInverseJoins; JoinTable assocTable = propertyHolder.getJoinTable( property ); CollectionTable collectionTable = property.getAnnotation( CollectionTable.class ); - if ( assocTable != null || collectionTable != null ) { final String catalog; @@ -2181,6 +2180,8 @@ public final class AnnotationBinder { final UniqueConstraint[] uniqueConstraints; final JoinColumn[] joins; final JoinColumn[] inverseJoins; + final javax.persistence.Index[] jpaIndexes; + //JPA 2 has priority if ( collectionTable != null ) { @@ -2190,6 +2191,7 @@ public final class AnnotationBinder { uniqueConstraints = collectionTable.uniqueConstraints(); joins = collectionTable.joinColumns(); inverseJoins = null; + jpaIndexes = collectionTable.indexes(); } else { catalog = assocTable.catalog(); @@ -2198,10 +2200,13 @@ public final class AnnotationBinder { uniqueConstraints = assocTable.uniqueConstraints(); joins = assocTable.joinColumns(); inverseJoins = assocTable.inverseJoinColumns(); + jpaIndexes = assocTable.indexes(); } collectionBinder.setExplicitAssociationTable( true ); - + if ( jpaIndexes != null && jpaIndexes.length > 0 ) { + associationTableBinder.setJpaIndex( jpaIndexes ); + } if ( !BinderHelper.isEmptyAnnotationValue( schema ) ) { associationTableBinder.setSchema( schema ); } @@ -2212,7 +2217,7 @@ public final class AnnotationBinder { associationTableBinder.setName( tableName ); } associationTableBinder.setUniqueConstraints( uniqueConstraints ); - + associationTableBinder.setJpaIndex( jpaIndexes ); //set check constaint in the second pass annJoins = joins.length == 0 ? null : joins; annInverseJoins = inverseJoins == null || inverseJoins.length == 0 ? null : inverseJoins; diff --git a/hibernate-core/src/main/java/org/hibernate/cfg/Configuration.java b/hibernate-core/src/main/java/org/hibernate/cfg/Configuration.java index 053f19f8f8..fb3dce778c 100644 --- a/hibernate-core/src/main/java/org/hibernate/cfg/Configuration.java +++ b/hibernate-core/src/main/java/org/hibernate/cfg/Configuration.java @@ -251,6 +251,7 @@ public class Configuration implements Serializable { private Set defaultNamedGenerators; private Map generatorTables; private Map> uniqueConstraintHoldersByTable; + private Map> jpaIndexHoldersByTable; private Map mappedByResolver; private Map propertyRefResolver; private Map anyMetaDefs; @@ -324,6 +325,7 @@ public class Configuration implements Serializable { defaultSqlResultSetMappingNames = new HashSet(); defaultNamedGenerators = new HashSet(); uniqueConstraintHoldersByTable = new HashMap>(); + jpaIndexHoldersByTable = new HashMap>( ); mappedByResolver = new HashMap(); propertyRefResolver = new HashMap(); caches = new ArrayList(); @@ -1380,6 +1382,17 @@ public class Configuration implements Serializable { buildUniqueKeyFromColumnNames( table, keyName, holder.getColumns() ); } } + for(Table table : jpaIndexHoldersByTable.keySet()){ + final List jpaIndexHolders = jpaIndexHoldersByTable.get( table ); + int uniqueIndexPerTable = 0; + for ( JPAIndexHolder holder : jpaIndexHolders ) { + uniqueIndexPerTable++; + final String keyName = StringHelper.isEmpty( holder.getName() ) + ? "idx_"+table.getName()+"_" + uniqueIndexPerTable + : holder.getName(); + buildUniqueKeyFromColumnNames( table, keyName, holder.getColumns(), holder.getOrdering(), holder.isUnique() ); + } + } } private void processSecondPassesOfType(Class type) { @@ -1533,7 +1546,11 @@ public class Configuration implements Serializable { } } - private void buildUniqueKeyFromColumnNames(Table table, String keyName, String[] columnNames) { + private void buildUniqueKeyFromColumnNames(Table table, String keyName, String[] columnNames){ + buildUniqueKeyFromColumnNames( table, keyName, columnNames, null, true ); + } + + private void buildUniqueKeyFromColumnNames(Table table, String keyName, String[] columnNames, String[] orderings, boolean unique) { keyName = normalizer.normalizeIdentifierQuoting( keyName ); int size = columnNames.length; @@ -1553,13 +1570,29 @@ public class Configuration implements Serializable { unboundNoLogical.add( new Column( logicalColumnName ) ); } } - UniqueKey uk = table.getOrCreateUniqueKey( keyName ); - for ( Column column : columns ) { - if ( table.containsColumn( column ) ) { - uk.addColumn( column ); - unbound.remove( column ); + if ( unique ) { + UniqueKey uk = table.getOrCreateUniqueKey( keyName ); + for ( int i = 0; i < columns.length; i++ ) { + Column column = columns[i]; + String order = orderings != null ? orderings[i] : null; + if ( table.containsColumn( column ) ) { + uk.addColumn( column, order ); + unbound.remove( column ); + } } } + else { + Index index = table.getOrCreateIndex( keyName ); + for ( int i = 0; i < columns.length; i++ ) { + Column column = columns[i]; + String order = orderings != null ? orderings[i] : null; + if ( table.containsColumn( column ) ) { + index.addColumn( column, order ); + unbound.remove( column ); + } + } + } + if ( unbound.size() > 0 || unboundNoLogical.size() > 0 ) { StringBuilder sb = new StringBuilder( "Unable to create unique key constraint (" ); for ( String columnName : columnNames ) { @@ -3309,6 +3342,15 @@ public class Configuration implements Serializable { holderList.addAll( uniqueConstraintHolders ); } + public void addJpaIndexHolders(Table table, List holders) { + List holderList = jpaIndexHoldersByTable.get( table ); + if ( holderList == null ) { + holderList = new ArrayList(); + jpaIndexHoldersByTable.put( table, holderList ); + } + holderList.addAll( holders ); + } + public void addMappedBy(String entityName, String propertyName, String inversePropertyName) { mappedByResolver.put( entityName + "." + propertyName, inversePropertyName ); } diff --git a/hibernate-core/src/main/java/org/hibernate/cfg/IndexOrUniqueKeySecondPass.java b/hibernate-core/src/main/java/org/hibernate/cfg/IndexOrUniqueKeySecondPass.java index 4a74fdb18b..7ba0adf99e 100644 --- a/hibernate-core/src/main/java/org/hibernate/cfg/IndexOrUniqueKeySecondPass.java +++ b/hibernate-core/src/main/java/org/hibernate/cfg/IndexOrUniqueKeySecondPass.java @@ -42,7 +42,6 @@ public class IndexOrUniqueKeySecondPass implements SecondPass { private Table table; private final String indexName; private final String[] columns; - private final String[] ordering; private final Mappings mappings; private final Ejb3Column column; private final boolean unique; @@ -54,46 +53,10 @@ public class IndexOrUniqueKeySecondPass implements SecondPass { this.table = table; this.indexName = indexName; this.columns = columns; - this.ordering = null; this.mappings = mappings; this.column = null; this.unique = false; } - //used for the new JPA 2.1 @Index - public IndexOrUniqueKeySecondPass(Table table, String indexName, String columnList, Mappings mappings, boolean unique) { - this.table = table; - StringTokenizer tokenizer = new StringTokenizer( columnList, "," ); - List tmp = new ArrayList(); - while ( tokenizer.hasMoreElements() ) { - tmp.add( tokenizer.nextToken().trim() ); - } - this.indexName = StringHelper.isNotEmpty( indexName ) ? indexName : "IDX_" + table.uniqueColumnString( tmp.iterator() ); - this.columns = new String[tmp.size()]; - this.ordering = new String[tmp.size()]; - initializeColumns(columns, ordering, tmp); - this.mappings = mappings; - this.column = null; - this.unique = unique; - } - - private void initializeColumns(String[] columns, String[] ordering, List list) { - for ( int i = 0, size = list.size(); i < size; i++ ) { - final String description = list.get( i ); - final String tmp = description.toLowerCase(); - if ( tmp.endsWith( " desc" ) ) { - columns[i] = description.substring( 0, description.length() - 5 ); - ordering[i] = "desc"; - } - else if ( tmp.endsWith( " asc" ) ) { - columns[i] = description.substring( 0, description.length() - 4 ); - ordering[i] = "asc"; - } - else { - columns[i] = description; - ordering[i] = null; - } - } - } /** @@ -112,23 +75,21 @@ public class IndexOrUniqueKeySecondPass implements SecondPass { this.columns = null; this.mappings = mappings; this.unique = unique; - this.ordering = null; } @Override public void doSecondPass(Map persistentClasses) throws MappingException { if ( columns != null ) { for ( int i = 0; i < columns.length; i++ ) { - final String order = ordering != null ? ordering[i] : null; - addConstraintToColumn( columns[i], order ); + addConstraintToColumn( columns[i] ); } } if ( column != null ) { this.table = column.getTable(); - addConstraintToColumn( mappings.getLogicalColumnName( column.getMappingColumn().getQuotedName(), table ), null ); + addConstraintToColumn( mappings.getLogicalColumnName( column.getMappingColumn().getQuotedName(), table ) ); } } - private void addConstraintToColumn(final String columnName, final String ordering) { + private void addConstraintToColumn(final String columnName ) { Column column = table.getColumn( new Column( mappings.getPhysicalColumnName( columnName, table ) @@ -140,8 +101,8 @@ public class IndexOrUniqueKeySecondPass implements SecondPass { ); } if ( unique ) - table.getOrCreateUniqueKey( indexName ).addColumn( column, ordering ); + table.getOrCreateUniqueKey( indexName ).addColumn( column ); else - table.getOrCreateIndex( indexName ).addColumn( column, ordering ); + table.getOrCreateIndex( indexName ).addColumn( column ); } } diff --git a/hibernate-core/src/main/java/org/hibernate/cfg/JPAIndexHolder.java b/hibernate-core/src/main/java/org/hibernate/cfg/JPAIndexHolder.java new file mode 100644 index 0000000000..bd5f379e88 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/cfg/JPAIndexHolder.java @@ -0,0 +1,88 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2010, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.cfg; + +import java.util.ArrayList; +import java.util.List; +import java.util.StringTokenizer; +import javax.persistence.Index; + +/** + * @author Strong Liu + */ +public class JPAIndexHolder { + + private final String name; + private final String[] columns; + private final String[] ordering; + private final boolean unique; + + public JPAIndexHolder(Index index) { + StringTokenizer tokenizer = new StringTokenizer( index.columnList(), "," ); + List tmp = new ArrayList(); + while ( tokenizer.hasMoreElements() ) { + tmp.add( tokenizer.nextToken().trim() ); + } + this.name = index.name(); + this.columns = new String[tmp.size()]; + this.ordering = new String[tmp.size()]; + this.unique = index.unique(); + initializeColumns( columns, ordering, tmp ); + } + + public String[] getColumns() { + return columns; + } + + public String getName() { + return name; + } + + public String[] getOrdering() { + return ordering; + } + + public boolean isUnique() { + return unique; + } + + private void initializeColumns(String[] columns, String[] ordering, List list) { + for ( int i = 0, size = list.size(); i < size; i++ ) { + final String description = list.get( i ); + final String tmp = description.toLowerCase(); + if ( tmp.endsWith( " desc" ) ) { + columns[i] = description.substring( 0, description.length() - 5 ); + ordering[i] = "desc"; + } + else if ( tmp.endsWith( " asc" ) ) { + columns[i] = description.substring( 0, description.length() - 4 ); + ordering[i] = "asc"; + } + else { + columns[i] = description; + ordering[i] = null; + } + } + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/cfg/Mappings.java b/hibernate-core/src/main/java/org/hibernate/cfg/Mappings.java index 2aa183c06d..a0d6543fc6 100644 --- a/hibernate-core/src/main/java/org/hibernate/cfg/Mappings.java +++ b/hibernate-core/src/main/java/org/hibernate/cfg/Mappings.java @@ -721,6 +721,8 @@ public interface Mappings { public void addUniqueConstraintHolders(Table table, List uniqueConstraintHolders); + public void addJpaIndexHolders(Table table, List jpaIndexHolders); + public void addMappedBy(String entityName, String propertyName, String inversePropertyName); public String getFromMappedBy(String entityName, String propertyName); diff --git a/hibernate-core/src/main/java/org/hibernate/cfg/annotations/SetBinder.java b/hibernate-core/src/main/java/org/hibernate/cfg/annotations/SetBinder.java index a0475a12dc..4df97b1a01 100644 --- a/hibernate-core/src/main/java/org/hibernate/cfg/annotations/SetBinder.java +++ b/hibernate-core/src/main/java/org/hibernate/cfg/annotations/SetBinder.java @@ -23,10 +23,7 @@ */ package org.hibernate.cfg.annotations; -import org.jboss.logging.Logger; - import org.hibernate.annotations.OrderBy; -import org.hibernate.internal.CoreMessageLogger; import org.hibernate.mapping.Collection; import org.hibernate.mapping.PersistentClass; @@ -36,7 +33,6 @@ import org.hibernate.mapping.PersistentClass; * @author Matthew Inger */ public class SetBinder extends CollectionBinder { - private static final CoreMessageLogger LOG = Logger.getMessageLogger(CoreMessageLogger.class, SetBinder.class.getName()); public SetBinder() { } diff --git a/hibernate-core/src/main/java/org/hibernate/cfg/annotations/TableBinder.java b/hibernate-core/src/main/java/org/hibernate/cfg/annotations/TableBinder.java index 8a80098ab3..27ffba5a29 100644 --- a/hibernate-core/src/main/java/org/hibernate/cfg/annotations/TableBinder.java +++ b/hibernate-core/src/main/java/org/hibernate/cfg/annotations/TableBinder.java @@ -36,6 +36,7 @@ import org.hibernate.annotations.Index; import org.hibernate.cfg.BinderHelper; import org.hibernate.cfg.Ejb3JoinColumn; import org.hibernate.cfg.IndexOrUniqueKeySecondPass; +import org.hibernate.cfg.JPAIndexHolder; import org.hibernate.cfg.Mappings; import org.hibernate.cfg.NamingStrategy; import org.hibernate.cfg.ObjectNameNormalizer; @@ -80,6 +81,7 @@ public class TableBinder { private String ownerEntity; private String associatedEntity; private boolean isJPA2ElementCollection; + private List jpaIndexHolders; public void setSchema(String schema) { this.schema = schema; @@ -105,6 +107,10 @@ public class TableBinder { this.uniqueConstraints = TableBinder.buildUniqueConstraintHolders( uniqueConstraints ); } + public void setJpaIndex(javax.persistence.Index[] jpaIndex){ + this.jpaIndexHolders = buildJpaIndexHolder( jpaIndex ); + } + public void setConstraints(String constraints) { this.constraints = constraints; } @@ -183,6 +189,7 @@ public class TableBinder { namingStrategyHelper, isAbstract, uniqueConstraints, + jpaIndexHolders, constraints, denormalizedSuperTable, mappings, @@ -190,6 +197,7 @@ public class TableBinder { ); } + private ObjectNameSource buildNameContext(String unquotedOwnerTable, String unquotedAssocTable) { String logicalName = mappings.getNamingStrategy().logicalCollectionTableName( name, @@ -211,10 +219,11 @@ public class TableBinder { ObjectNameNormalizer.NamingStrategyHelper namingStrategyHelper, boolean isAbstract, List uniqueConstraints, + List jpaIndexHolders, String constraints, Table denormalizedSuperTable, Mappings mappings, - String subselect) { + String subselect){ schema = BinderHelper.isEmptyAnnotationValue( schema ) ? mappings.getSchemaName() : schema; catalog = BinderHelper.isEmptyAnnotationValue( catalog ) ? mappings.getCatalogName() : catalog; @@ -244,10 +253,14 @@ public class TableBinder { ); } - if ( uniqueConstraints != null && uniqueConstraints.size() > 0 ) { + if ( CollectionHelper.isNotEmpty( uniqueConstraints ) ) { mappings.addUniqueConstraintHolders( table, uniqueConstraints ); } + if ( CollectionHelper.isNotEmpty( jpaIndexHolders ) ) { + mappings.addJpaIndexHolders( table, jpaIndexHolders ); + } + if ( constraints != null ) table.addCheckConstraint( constraints ); // logicalName is null if we are in the second pass @@ -258,6 +271,23 @@ public class TableBinder { return table; } + + + public static Table buildAndFillTable( + String schema, + String catalog, + ObjectNameSource nameSource, + ObjectNameNormalizer.NamingStrategyHelper namingStrategyHelper, + boolean isAbstract, + List uniqueConstraints, + String constraints, + Table denormalizedSuperTable, + Mappings mappings, + String subselect) { + return buildAndFillTable( schema, catalog, nameSource, namingStrategyHelper, isAbstract, uniqueConstraints, null, constraints + , denormalizedSuperTable, mappings, subselect); + } + /** * @deprecated Use {@link #buildAndFillTable} instead. */ @@ -515,18 +545,15 @@ public class TableBinder { } public static void addIndexes(Table hibTable, javax.persistence.Index[] indexes, Mappings mappings) { - for ( javax.persistence.Index index : indexes ) { - //no need to handle inSecondPass here since it is only called from EntityBinder - mappings.addSecondPass( - new IndexOrUniqueKeySecondPass( - hibTable, - index.name(), - index.columnList(), - mappings, - index.unique() - ) - ); + mappings.addJpaIndexHolders( hibTable, buildJpaIndexHolder( indexes ) ); + } + + public static List buildJpaIndexHolder(javax.persistence.Index[] indexes){ + List holders = new ArrayList( indexes.length ); + for(javax.persistence.Index index : indexes){ + holders.add( new JPAIndexHolder( index ) ); } + return holders; } /** diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/embedded/WealthyPerson.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/embedded/WealthyPerson.java index d859fe3911..ae3ab486e6 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/embedded/WealthyPerson.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/embedded/WealthyPerson.java @@ -4,6 +4,7 @@ import java.util.Set; import javax.persistence.CollectionTable; import javax.persistence.ElementCollection; import javax.persistence.Entity; +import javax.persistence.Index; @Entity public class WealthyPerson extends Person { @@ -15,6 +16,6 @@ public class WealthyPerson extends Person { protected Set
legacyVacationHomes = new HashSet
(); @ElementCollection - @CollectionTable(name = "WelPers_VacHomes") + @CollectionTable(name = "WelPers_VacHomes", indexes = @Index( columnList = "countryName, type_id")) protected Set
explicitVacationHomes = new HashSet
(); } diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/index/jpa/IndexTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/index/jpa/IndexTest.java index fed063a0fd..f072f83d17 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/index/jpa/IndexTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/index/jpa/IndexTest.java @@ -30,13 +30,24 @@ import org.junit.Test; import static org.junit.Assert.*; import org.hibernate.internal.util.StringHelper; +import org.hibernate.mapping.Bag; import org.hibernate.mapping.Column; import org.hibernate.mapping.Index; import org.hibernate.mapping.Join; +import org.hibernate.mapping.List; import org.hibernate.mapping.PersistentClass; +import org.hibernate.mapping.Property; +import org.hibernate.mapping.Set; +import org.hibernate.mapping.Table; import org.hibernate.mapping.UniqueKey; +import org.hibernate.mapping.Value; +import org.hibernate.test.annotations.embedded.Address; +import org.hibernate.test.annotations.embedded.AddressType; import org.hibernate.test.annotations.embedded.Book; +import org.hibernate.test.annotations.embedded.Person; import org.hibernate.test.annotations.embedded.Summary; +import org.hibernate.test.annotations.embedded.WealthyPerson; +import org.hibernate.test.event.collection.detached.*; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; /** @@ -45,11 +56,20 @@ import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; public class IndexTest extends BaseCoreFunctionalTestCase { @Override protected Class[] getAnnotatedClasses() { - return new Class[] { Car.class, Book.class, Summary.class }; + return new Class[] { Car.class, + Book.class, + Summary.class, + WealthyPerson.class, + Person.class, + AddressType.class, + Address.class, + Alias.class, + org.hibernate.test.event.collection.detached.Character.class + }; } @Test - public void testBasicIndex() { + public void testTableIndex() { PersistentClass entity = configuration().getClassMapping( Car.class.getName() ); Iterator itr = entity.getTable().getUniqueKeyIterator(); assertTrue( itr.hasNext() ); @@ -94,4 +114,50 @@ public class IndexTest extends BaseCoreFunctionalTestCase { assertSame( join.getTable(), index.getTable() ); } + + @Test + public void testCollectionTableIndex(){ + PersistentClass entity = configuration().getClassMapping( WealthyPerson.class.getName() ); + Property property = entity.getProperty( "explicitVacationHomes" ); + Set set = (Set)property.getValue(); + Table collectionTable = set.getCollectionTable(); + + Iterator itr = collectionTable.getIndexIterator(); + assertTrue( itr.hasNext() ); + Index index = itr.next(); + assertFalse( itr.hasNext() ); + assertTrue( "index name is not generated", StringHelper.isNotEmpty( index.getName() ) ); + assertEquals( 2, index.getColumnSpan() ); + Iterator columnIterator = index.getColumnIterator(); + Column column = columnIterator.next(); + assertEquals( "countryName", column.getName() ); + column = columnIterator.next(); + assertEquals( "type_id", column.getName() ); + assertSame( collectionTable, index.getTable() ); + + } + + @Test + public void testJoinTableIndex(){ + PersistentClass entity = configuration().getClassMapping( Alias.class.getName() ); + Property property = entity.getProperty( "characters" ); + Bag set = (Bag)property.getValue(); + Table collectionTable = set.getCollectionTable(); + + Iterator itr = collectionTable.getUniqueKeyIterator(); + assertTrue( itr.hasNext() ); + UniqueKey index = itr.next(); + assertFalse( itr.hasNext() ); + assertTrue( "index name is not generated", StringHelper.isNotEmpty( index.getName() ) ); + assertEquals( 1, index.getColumnSpan() ); + Iterator columnIterator = index.getColumnIterator(); + Column column = columnIterator.next(); + assertEquals( "characters_id", column.getName() ); + assertSame( collectionTable, index.getTable() ); + } + + @Test + public void testTableGeneratorIndex(){ + //todo + } } diff --git a/hibernate-core/src/test/java/org/hibernate/test/event/collection/detached/Alias.java b/hibernate-core/src/test/java/org/hibernate/test/event/collection/detached/Alias.java index ecab38368a..4e9927ad56 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/event/collection/detached/Alias.java +++ b/hibernate-core/src/test/java/org/hibernate/test/event/collection/detached/Alias.java @@ -26,6 +26,7 @@ package org.hibernate.test.event.collection.detached; import javax.persistence.CascadeType; import javax.persistence.Entity; import javax.persistence.Id; +import javax.persistence.Index; import javax.persistence.JoinColumn; import javax.persistence.JoinTable; import javax.persistence.ManyToMany; @@ -68,7 +69,7 @@ public class Alias implements Identifiable { } @ManyToMany( cascade = CascadeType.ALL ) - @JoinTable( name = "CHARACTER_ALIAS" ) + @JoinTable( name = "CHARACTER_ALIAS", indexes = @Index( columnList = "characters_id", unique = true)) // @JoinTable( // name = "CHARACTER_ALIAS", // joinColumns = @JoinColumn(name="ALIAS_ID", referencedColumnName="ID"),