HHH-6287 Bind @UniqueConstraint
This commit is contained in:
parent
77e555ff05
commit
632150ad72
|
@ -108,6 +108,7 @@ public class MultipleHiLoPerTableGenerator implements PersistentIdentifierGenera
|
|||
private Identifier qualifiedValueColumnName;
|
||||
|
||||
private String tableName;
|
||||
private Table table;
|
||||
private String pkColumnName;
|
||||
private String valueColumnName;
|
||||
|
||||
|
@ -129,6 +130,15 @@ public class MultipleHiLoPerTableGenerator implements PersistentIdentifierGenera
|
|||
return tableName;
|
||||
}
|
||||
|
||||
/**
|
||||
* The bound Table for this generator.
|
||||
*
|
||||
* @return The table.
|
||||
*/
|
||||
public final Table getTable() {
|
||||
return table;
|
||||
}
|
||||
|
||||
public synchronized Serializable generate(final SessionImplementor session, Object obj) {
|
||||
final WorkExecutorVisitable<IntegralDataTypeHolder> work = new AbstractReturningWork<IntegralDataTypeHolder>() {
|
||||
@Override
|
||||
|
@ -279,7 +289,7 @@ public class MultipleHiLoPerTableGenerator implements PersistentIdentifierGenera
|
|||
final Dialect dialect = database.getJdbcEnvironment().getDialect();
|
||||
|
||||
final Schema schema = database.getSchemaFor( qualifiedTableName );
|
||||
final Table table = schema.createTable( qualifiedTableName.getName(), qualifiedTableName.getName() );
|
||||
table = schema.createTable( qualifiedTableName.getName(), qualifiedTableName.getName() );
|
||||
|
||||
final Column pkColumn = table.createColumn( qualifiedPkColumnName );
|
||||
table.getPrimaryKey().addColumn( pkColumn );
|
||||
|
|
|
@ -33,8 +33,6 @@ import java.util.Collections;
|
|||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.LockMode;
|
||||
import org.hibernate.LockOptions;
|
||||
|
@ -58,7 +56,9 @@ import org.hibernate.metamodel.spi.relational.Column;
|
|||
import org.hibernate.metamodel.spi.relational.Database;
|
||||
import org.hibernate.metamodel.spi.relational.Identifier;
|
||||
import org.hibernate.metamodel.spi.relational.ObjectName;
|
||||
import org.hibernate.metamodel.spi.relational.Table;
|
||||
import org.hibernate.type.Type;
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
/**
|
||||
* An enhanced version of table-based id generation.
|
||||
|
@ -170,6 +170,7 @@ public class TableGenerator implements PersistentIdentifierGenerator, Configurab
|
|||
private Identifier qualifiedValueColumnName;
|
||||
|
||||
private String tableName;
|
||||
private Table table;
|
||||
|
||||
private String segmentColumnName;
|
||||
private String segmentValue;
|
||||
|
@ -209,6 +210,15 @@ public class TableGenerator implements PersistentIdentifierGenerator, Configurab
|
|||
return tableName;
|
||||
}
|
||||
|
||||
/**
|
||||
* The bound Table for this generator.
|
||||
*
|
||||
* @return The table.
|
||||
*/
|
||||
public final Table getTable() {
|
||||
return table;
|
||||
}
|
||||
|
||||
/**
|
||||
* The name of the column in which we store the segment to which each row
|
||||
* belongs. The value here acts as PK.
|
||||
|
@ -563,7 +573,7 @@ public class TableGenerator implements PersistentIdentifierGenerator, Configurab
|
|||
public void registerExportables(Database database) {
|
||||
final Dialect dialect = database.getJdbcEnvironment().getDialect();
|
||||
|
||||
org.hibernate.metamodel.spi.relational.Table table = database.getSchemaFor( qualifiedTableName )
|
||||
table = database.getSchemaFor( qualifiedTableName )
|
||||
.createTable( qualifiedTableName.getName(), qualifiedTableName.getName() );
|
||||
|
||||
Column segmentColumn = table.createColumn( qualifiedSegmentColumnName );
|
||||
|
|
|
@ -25,7 +25,6 @@ package org.hibernate.metamodel.internal;
|
|||
|
||||
import static org.hibernate.engine.spi.SyntheticAttributeHelper.SYNTHETIC_COMPOSITE_ID_ATTRIBUTE_NAME;
|
||||
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
|
@ -56,7 +55,9 @@ import org.hibernate.engine.spi.FilterDefinition;
|
|||
import org.hibernate.id.EntityIdentifierNature;
|
||||
import org.hibernate.id.IdentifierGenerator;
|
||||
import org.hibernate.id.IdentityGenerator;
|
||||
import org.hibernate.id.MultipleHiLoPerTableGenerator;
|
||||
import org.hibernate.id.PersistentIdentifierGenerator;
|
||||
import org.hibernate.id.enhanced.TableGenerator;
|
||||
import org.hibernate.id.factory.IdentifierGeneratorFactory;
|
||||
import org.hibernate.internal.CoreMessageLogger;
|
||||
import org.hibernate.internal.FilterConfiguration;
|
||||
|
@ -2887,7 +2888,8 @@ public class Binder {
|
|||
if ( UniqueConstraintSource.class.isInstance( constraintSource ) ) {
|
||||
UniqueKey uk = new UniqueKey();
|
||||
|
||||
final TableSpecification table = entityBinding.locateTable( constraintSource.getTableName() );
|
||||
TableSpecification table = findUniqueConstraintTable( entityBinding, constraintSource.getTableName() );
|
||||
|
||||
final List<String> columnNames = constraintSource.columnNames();
|
||||
final String constraintName = StringHelper.isEmpty( constraintSource.name() )
|
||||
? UniqueKey.generateName( table, columnNames.toArray( new String[columnNames.size()] ) )
|
||||
|
@ -2902,6 +2904,52 @@ public class Binder {
|
|||
}
|
||||
}
|
||||
|
||||
private TableSpecification findUniqueConstraintTable(EntityBinding entityBinding, String tableName) {
|
||||
try {
|
||||
return entityBinding.locateTable( tableName );
|
||||
}
|
||||
catch ( AssertionFailure e ) {
|
||||
Identifier identifier = Identifier.toIdentifier( tableName );
|
||||
|
||||
// TODO: Make TableGenerator & MultipleHiLoPerTableGenerator extend an abstract?
|
||||
// @TableGenerator
|
||||
IdentifierGenerator idGenerator = entityBinding.getHierarchyDetails().getEntityIdentifier().getIdentifierGenerator();
|
||||
if (idGenerator instanceof TableGenerator) {
|
||||
Table generatorTable = ((TableGenerator) idGenerator).getTable();
|
||||
if (generatorTable != null && generatorTable.getLogicalName().equals( identifier ) ) {
|
||||
return generatorTable;
|
||||
}
|
||||
}
|
||||
else if (idGenerator instanceof MultipleHiLoPerTableGenerator) {
|
||||
Table generatorTable = ((MultipleHiLoPerTableGenerator) idGenerator).getTable();
|
||||
if (generatorTable != null && generatorTable.getLogicalName().equals( identifier ) ) {
|
||||
return generatorTable;
|
||||
}
|
||||
}
|
||||
|
||||
// @JoinTable and @CollectionTable
|
||||
Iterator<AttributeBinding> attributeBindings = entityBinding.attributeBindings().iterator();
|
||||
while (attributeBindings.hasNext()) {
|
||||
AttributeBinding attributeBinding = attributeBindings.next();
|
||||
if (attributeBinding instanceof PluralAttributeBinding) {
|
||||
PluralAttributeBinding pluralAttributeBinding = (PluralAttributeBinding) attributeBinding;
|
||||
|
||||
TableSpecification pluralTable = pluralAttributeBinding.getPluralAttributeKeyBinding().getCollectionTable();
|
||||
if (pluralTable != null && pluralTable.getLogicalName().equals( identifier ) ) {
|
||||
return pluralTable;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
throw new AssertionFailure(
|
||||
String.format(
|
||||
"Unable to find locate table %s",
|
||||
tableName
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
private List<RelationalValueBinding> bindValues(
|
||||
final AttributeBindingContainer attributeBindingContainer,
|
||||
final RelationalValueSourceContainer valueSourceContainer,
|
||||
|
|
|
@ -331,6 +331,36 @@ public class EntitySourceImpl implements EntitySource {
|
|||
}
|
||||
}
|
||||
|
||||
if ( entityClass.hostsAnnotation( JPADotNames.COLLECTION_TABLE ) ) {
|
||||
List<AnnotationInstance> collectionTables = JandexHelper.getAnnotations(
|
||||
entityClass.getClassInfo(), JPADotNames.COLLECTION_TABLE );
|
||||
for (AnnotationInstance collectionTable : collectionTables) {
|
||||
String tableName = JandexHelper.getValue( collectionTable, "name", String.class );
|
||||
addUniqueConstraints( constraintSources, collectionTable, tableName );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if ( entityClass.hostsAnnotation( JPADotNames.JOIN_TABLE ) ) {
|
||||
List<AnnotationInstance> joinTables = JandexHelper.getAnnotations(
|
||||
entityClass.getClassInfo(), JPADotNames.JOIN_TABLE );
|
||||
for (AnnotationInstance joinTable : joinTables) {
|
||||
String tableName = JandexHelper.getValue( joinTable, "name", String.class );
|
||||
addUniqueConstraints( constraintSources, joinTable, tableName );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if ( entityClass.hostsAnnotation( JPADotNames.TABLE_GENERATOR ) ) {
|
||||
List<AnnotationInstance> tableGenerators = JandexHelper.getAnnotations(
|
||||
entityClass.getClassInfo(), JPADotNames.TABLE_GENERATOR );
|
||||
for (AnnotationInstance tableGenerator : tableGenerators) {
|
||||
String tableName = JandexHelper.getValue( tableGenerator, "table", String.class );
|
||||
addUniqueConstraints( constraintSources, tableGenerator, tableName );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return constraintSources;
|
||||
}
|
||||
|
||||
|
|
|
@ -24,44 +24,66 @@
|
|||
|
||||
package org.hibernate.metamodel.internal.source.annotations.entity;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Table;
|
||||
import javax.persistence.UniqueConstraint;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.hibernate.metamodel.spi.binding.EntityBinding;
|
||||
import org.hibernate.metamodel.spi.relational.TableSpecification;
|
||||
import org.hibernate.metamodel.spi.relational.UniqueKey;
|
||||
import org.hibernate.testing.junit4.BaseAnnotationBindingTestCase;
|
||||
import org.hibernate.testing.junit4.Resources;
|
||||
|
||||
import static junit.framework.Assert.assertEquals;
|
||||
import static junit.framework.Assert.assertNotNull;
|
||||
import static junit.framework.Assert.assertTrue;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import javax.persistence.CollectionTable;
|
||||
import javax.persistence.ElementCollection;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.GenerationType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.JoinTable;
|
||||
import javax.persistence.ManyToMany;
|
||||
import javax.persistence.OrderColumn;
|
||||
import javax.persistence.Table;
|
||||
import javax.persistence.TableGenerator;
|
||||
import javax.persistence.UniqueConstraint;
|
||||
|
||||
import org.hibernate.id.MultipleHiLoPerTableGenerator;
|
||||
import org.hibernate.metamodel.spi.binding.EntityBinding;
|
||||
import org.hibernate.metamodel.spi.relational.TableSpecification;
|
||||
import org.hibernate.metamodel.spi.relational.UniqueKey;
|
||||
import org.hibernate.test.util.SchemaUtil;
|
||||
import org.hibernate.testing.junit4.BaseAnnotationBindingTestCase;
|
||||
import org.hibernate.testing.junit4.Resources;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* test for {@link javax.persistence.UniqueConstraint}
|
||||
*
|
||||
* @author Strong Liu
|
||||
* @author Brett Meyer
|
||||
*/
|
||||
public class UniqueConstraintBindingTest extends BaseAnnotationBindingTestCase {
|
||||
@Test
|
||||
@Resources(annotatedClasses = TableWithUniqueConstraint.class)
|
||||
@Resources(annotatedClasses = { TableWithUniqueConstraint.class, SecondTable.class })
|
||||
public void testTableUniqueConstraints() {
|
||||
EntityBinding binding = getEntityBinding( TableWithUniqueConstraint.class );
|
||||
TableSpecification table = binding.getPrimaryTable();
|
||||
testTableUniqueConstraints( binding.getPrimaryTable(), "u1", 2 );
|
||||
testTableUniqueConstraints( ( (MultipleHiLoPerTableGenerator) binding.getHierarchyDetails()
|
||||
.getEntityIdentifier().getIdentifierGenerator() ).getTable(), "u2", 1 );
|
||||
testTableUniqueConstraints( SchemaUtil.getCollection( TableWithUniqueConstraint.class, "secondTables", meta )
|
||||
.getPluralAttributeKeyBinding().getCollectionTable(), "u3", 2 );
|
||||
testTableUniqueConstraints( SchemaUtil.getCollection( TableWithUniqueConstraint.class, "elements", meta )
|
||||
.getPluralAttributeKeyBinding().getCollectionTable(), "u4", 1 );
|
||||
}
|
||||
|
||||
private void testTableUniqueConstraints(TableSpecification table, String ukName, int ukNumColumns) {
|
||||
Iterable<UniqueKey> uniqueKeyIterable = table.getUniqueKeys();
|
||||
assertNotNull( uniqueKeyIterable );
|
||||
int i = 0;
|
||||
for ( UniqueKey key : uniqueKeyIterable ) {
|
||||
i++;
|
||||
assertEquals( "u1", key.getName() );
|
||||
assertEquals( ukName, key.getName() );
|
||||
assertTrue( table == key.getTable() );
|
||||
assertNotNull( key.getColumns() );
|
||||
assertEquals( "There should be two columns in the unique constraint", 2, key.getColumns().size() );
|
||||
assertEquals( "There should be two columns in the unique constraint", 2, key.getColumnSpan() );
|
||||
assertEquals( "There should be two columns in the unique constraint", ukNumColumns, key.getColumns().size() );
|
||||
assertEquals( "There should be two columns in the unique constraint", ukNumColumns, key.getColumnSpan() );
|
||||
}
|
||||
assertEquals( "There should only be one unique constraint", 1, i );
|
||||
}
|
||||
|
@ -70,8 +92,36 @@ public class UniqueConstraintBindingTest extends BaseAnnotationBindingTestCase {
|
|||
@Table(uniqueConstraints = { @UniqueConstraint(name = "u1", columnNames = { "name", "age" }) })
|
||||
class TableWithUniqueConstraint {
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.TABLE, generator = "fooGenerator")
|
||||
@TableGenerator(name = "fooGenerator", table = "foo_generator_table", valueColumnName = "fooGeneratorValue", uniqueConstraints = @UniqueConstraint(columnNames = "fooGeneratorValue", name = "u2"))
|
||||
int id;
|
||||
|
||||
String name;
|
||||
|
||||
int age;
|
||||
|
||||
@ManyToMany
|
||||
@JoinTable(name = "JoinTable", joinColumns = @JoinColumn(name = "secondTable"), inverseJoinColumns = @JoinColumn(name = "tableWithUniqueConstraint"), uniqueConstraints = @UniqueConstraint(columnNames = {
|
||||
"secondTable", "tableWithUniqueConstraint" }, name = "u3"))
|
||||
Set<SecondTable> secondTables;
|
||||
|
||||
@ElementCollection
|
||||
@CollectionTable(name = "CollectionTable", joinColumns = @JoinColumn(name = "element"), uniqueConstraints = @UniqueConstraint(columnNames = "element", name = "u4"))
|
||||
@OrderColumn(name = "element_index")
|
||||
public int[] elements;
|
||||
}
|
||||
|
||||
@Entity
|
||||
class SecondTable {
|
||||
@Id
|
||||
@GeneratedValue
|
||||
int id;
|
||||
|
||||
String name;
|
||||
|
||||
int age;
|
||||
|
||||
@ManyToMany(mappedBy = "secondTables")
|
||||
Set<TableWithUniqueConstraint> tableWithUniqueConstraint;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue