Skip to content

Commit 0eb87b7

Browse files
stliuhferentschik
authored andcommitted
HHH-6287 bind @Table.uniqueConstraints
1 parent ddc1bcc commit 0eb87b7

File tree

9 files changed

+161
-26
lines changed

9 files changed

+161
-26
lines changed

hibernate-core/src/main/java/org/hibernate/metamodel/relational/AbstractTableSpecification.java

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@
2424
package org.hibernate.metamodel.relational;
2525

2626
import java.util.ArrayList;
27+
import java.util.Collections;
28+
import java.util.LinkedHashMap;
2729
import java.util.LinkedHashSet;
2830
import java.util.List;
2931

@@ -34,26 +36,32 @@
3436
* @author Steve Ebersole
3537
*/
3638
public abstract class AbstractTableSpecification implements TableSpecification, ValueContainer {
37-
private final LinkedHashSet<SimpleValue> values = new LinkedHashSet<SimpleValue>();
39+
private final LinkedHashMap<String,SimpleValue> values = new LinkedHashMap<String,SimpleValue>();
3840
private PrimaryKey primaryKey = new PrimaryKey( this );
3941
private List<ForeignKey> foreignKeys = new ArrayList<ForeignKey>();
4042

4143
@Override
4244
public Iterable<SimpleValue> values() {
43-
return values;
45+
return values.values();
4446
}
4547

4648
@Override
47-
public Column createColumn(String name) {
49+
public Column getOrCreateColumn(String name) {
50+
if(values.containsKey( name )){
51+
return (Column) values.get( name );
52+
}
4853
final Column column = new Column( this, values.size(), name );
49-
values.add( column );
54+
values.put(name, column );
5055
return column;
5156
}
5257

5358
@Override
54-
public DerivedValue createDerivedValue(String fragment) {
59+
public DerivedValue getOrCreateDerivedValue(String fragment) {
60+
if(values.containsKey( fragment )){
61+
return (DerivedValue) values.get( fragment );
62+
}
5563
final DerivedValue value = new DerivedValue( this, values.size(), fragment );
56-
values.add( value );
64+
values.put(fragment, value );
5765
return value;
5866
}
5967

hibernate-core/src/main/java/org/hibernate/metamodel/relational/Table.java

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525

2626
import java.util.ArrayList;
2727
import java.util.HashSet;
28+
import java.util.LinkedHashMap;
2829
import java.util.List;
2930
import java.util.Set;
3031

@@ -39,8 +40,8 @@ public class Table extends AbstractTableSpecification implements ValueContainer,
3940
private final Identifier tableName;
4041
private final String qualifiedName;
4142

42-
private List<Index> indexes;
43-
private List<UniqueKey> uniqueKeys;
43+
private LinkedHashMap<String,Index> indexes;
44+
private LinkedHashMap<String,UniqueKey> uniqueKeys;
4445
private List<String> checkConstraints;
4546
private Set<String> comments;
4647

@@ -81,29 +82,35 @@ public String toLoggableString() {
8182

8283
@Override
8384
public Iterable<Index> getIndexes() {
84-
return indexes;
85+
return indexes.values();
8586
}
8687

8788
public Index getOrCreateIndex(String name) {
89+
if(indexes!=null && indexes.containsKey( name )){
90+
return indexes.get( name );
91+
}
8892
Index index = new Index( this, name );
8993
if ( indexes == null ) {
90-
indexes = new ArrayList<Index>();
94+
indexes = new LinkedHashMap<String,Index>();
9195
}
92-
indexes.add( index );
96+
indexes.put(name, index );
9397
return index;
9498
}
9599

96100
@Override
97101
public Iterable<UniqueKey> getUniqueKeys() {
98-
return uniqueKeys;
102+
return uniqueKeys.values();
99103
}
100104

101105
public UniqueKey getOrCreateUniqueKey(String name) {
106+
if(uniqueKeys!=null && uniqueKeys.containsKey( name )){
107+
return uniqueKeys.get( name );
108+
}
102109
UniqueKey uniqueKey = new UniqueKey( this, name );
103110
if ( uniqueKeys == null ) {
104-
uniqueKeys = new ArrayList<UniqueKey>();
111+
uniqueKeys = new LinkedHashMap<String,UniqueKey>();
105112
}
106-
uniqueKeys.add( uniqueKey );
113+
uniqueKeys.put(name, uniqueKey );
107114
return uniqueKey;
108115
}
109116

hibernate-core/src/main/java/org/hibernate/metamodel/relational/TableSpecification.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ public interface TableSpecification extends ValueContainer, Loggable {
5050
*
5151
* @return The generated column
5252
*/
53-
public Column createColumn(String name);
53+
public Column getOrCreateColumn(String name);
5454

5555
/**
5656
* Factory method for creating a {@link Column} associated with this container.
@@ -68,7 +68,7 @@ public interface TableSpecification extends ValueContainer, Loggable {
6868
*
6969
* @return The generated value.
7070
*/
71-
public DerivedValue createDerivedValue(String fragment);
71+
public DerivedValue getOrCreateDerivedValue(String fragment);
7272

7373
public Iterable<ForeignKey> getForeignKeys();
7474

hibernate-core/src/main/java/org/hibernate/metamodel/relational/state/ValueCreator.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,14 +54,14 @@ public static Column createColumn(TableSpecification table,
5454
if ( columnName == null ) {
5555
throw new IllegalArgumentException( "columnName must be non-null." );
5656
}
57-
Column value = table.createColumn( columnName );
57+
Column value = table.getOrCreateColumn( columnName );
5858
value.initialize( state, forceNonNullable, forceUnique );
5959
return value;
6060
}
6161

6262
public static DerivedValue createDerivedValue(TableSpecification table,
6363
DerivedValueRelationalState state) {
64-
return table.createDerivedValue( state.getFormula() );
64+
return table.getOrCreateDerivedValue( state.getFormula() );
6565
}
6666

6767
public static SimpleValue createSimpleValue(TableSpecification table,

hibernate-core/src/main/java/org/hibernate/metamodel/source/annotations/entity/EntityBinder.java

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,8 @@
5757
import org.hibernate.metamodel.domain.Hierarchical;
5858
import org.hibernate.metamodel.relational.Identifier;
5959
import org.hibernate.metamodel.relational.Schema;
60+
import org.hibernate.metamodel.relational.TableSpecification;
61+
import org.hibernate.metamodel.relational.UniqueKey;
6062
import org.hibernate.metamodel.source.annotations.HibernateDotNames;
6163
import org.hibernate.metamodel.source.annotations.JPADotNames;
6264
import org.hibernate.metamodel.source.annotations.entity.state.binding.AttributeBindingStateImpl;
@@ -116,12 +118,49 @@ public void bind() {
116118

117119
// bind all attributes - simple as well as associations
118120
bindAttributes( entityBinding );
119-
121+
bindTableUniqueConstraints( entityBinding );
120122
// last, but not least we initialize and register the new EntityBinding
121123
entityBinding.initialize( entityBindingState );
122124
meta.addEntity( entityBinding );
123125
}
124126

127+
private void bindTableUniqueConstraints(EntityBinding entityBinding) {
128+
AnnotationInstance tableAnnotation = JandexHelper.getSingleAnnotation(
129+
configuredClass.getClassInfo(),
130+
JPADotNames.TABLE
131+
);
132+
if ( tableAnnotation == null ) {
133+
return;
134+
}
135+
TableSpecification table = entityBinding.getBaseTable();
136+
bindUniqueConstraints( tableAnnotation, table );
137+
}
138+
139+
/**
140+
* Bind {@link javax.persistence.UniqueConstraint} to table as a {@link UniqueKey}
141+
*
142+
* @param tableAnnotation JPA annotations which has a {@code uniqueConstraints} attribute.
143+
* @param table Table which the UniqueKey bind to.
144+
*/
145+
private void bindUniqueConstraints(AnnotationInstance tableAnnotation,TableSpecification table) {
146+
AnnotationValue value = tableAnnotation.value( "uniqueConstraints" );
147+
if ( value == null ) {
148+
return;
149+
}
150+
AnnotationInstance[] uniqueConstraints = value.asNestedArray();
151+
for ( AnnotationInstance unique : uniqueConstraints ) {
152+
String name = unique.value( "name" ).asString();
153+
UniqueKey uniqueKey = table.getOrCreateUniqueKey( name );
154+
String[] columnNames = unique.value( "columnNames" ).asStringArray();
155+
if ( columnNames.length == 0 ) {
156+
//todo throw exception?
157+
}
158+
for ( String columnName : columnNames ) {
159+
uniqueKey.addColumn( table.getOrCreateColumn( columnName ) );
160+
}
161+
}
162+
}
163+
125164
private void bindInheritance(EntityBinding entityBinding) {
126165
entityBinding.setInheritanceType( configuredClass.getInheritanceType() );
127166
switch ( configuredClass.getInheritanceType() ) {

hibernate-core/src/test/java/org/hibernate/metamodel/binding/SimpleValueBindingTests.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ public void testBasicMiddleOutBuilding() {
6464

6565
entityBinding.getEntityIdentifier().setValueBinding( attributeBinding );
6666

67-
Column idColumn = table.createColumn( "id" );
67+
Column idColumn = table.getOrCreateColumn( "id" );
6868
idColumn.setDatatype( BIGINT );
6969
idColumn.setSize( Size.precision( 18, 0 ) );
7070
table.getPrimaryKey().addColumn( idColumn );

hibernate-core/src/test/java/org/hibernate/metamodel/relational/TableManipulationTests.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -52,15 +52,15 @@ public void testTableCreation() {
5252
assertNull( table.getPrimaryKey().getName() );
5353
assertFalse( table.values().iterator().hasNext() );
5454

55-
Column idColumn = table.createColumn( "id" );
55+
Column idColumn = table.getOrCreateColumn( "id" );
5656
idColumn.setDatatype( INTEGER );
5757
idColumn.setSize( Size.precision( 18, 0 ) );
5858
table.getPrimaryKey().addColumn( idColumn );
5959
table.getPrimaryKey().setName( "my_table_pk" );
6060
assertEquals( "my_table_pk", table.getPrimaryKey().getName() );
6161
assertEquals( "my_table.PK", table.getPrimaryKey().getExportIdentifier() );
6262

63-
Column col_1 = table.createColumn( "col_1" );
63+
Column col_1 = table.getOrCreateColumn( "col_1" );
6464
col_1.setDatatype( VARCHAR );
6565
col_1.setSize( Size.length( 512 ) );
6666

@@ -90,21 +90,21 @@ public void testBasicForeignKeyDefinition() {
9090
Schema schema = new Schema( null, null );
9191
Table book = schema.createTable( Identifier.toIdentifier( "BOOK" ) );
9292

93-
Column bookId = book.createColumn( "id" );
93+
Column bookId = book.getOrCreateColumn( "id" );
9494
bookId.setDatatype( INTEGER );
9595
bookId.setSize( Size.precision( 18, 0 ) );
9696
book.getPrimaryKey().addColumn( bookId );
9797
book.getPrimaryKey().setName( "BOOK_PK" );
9898

9999
Table page = schema.createTable( Identifier.toIdentifier( "PAGE" ) );
100100

101-
Column pageId = page.createColumn( "id" );
101+
Column pageId = page.getOrCreateColumn( "id" );
102102
pageId.setDatatype( INTEGER );
103103
pageId.setSize( Size.precision( 18, 0 ) );
104104
page.getPrimaryKey().addColumn( pageId );
105105
page.getPrimaryKey().setName( "PAGE_PK" );
106106

107-
Column pageBookId = page.createColumn( "BOOK_ID" );
107+
Column pageBookId = page.getOrCreateColumn( "BOOK_ID" );
108108
pageId.setDatatype( INTEGER );
109109
pageId.setSize( Size.precision( 18, 0 ) );
110110
ForeignKey pageBookFk = page.createForeignKey( book, "PAGE_BOOK_FK" );

hibernate-core/src/test/java/org/hibernate/metamodel/source/annotations/entity/BatchSizeBindingTests.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/*
22
* Hibernate, Relational Persistence for Idiomatic Java
33
*
4-
* Copyright (c) 2010, Red Hat Inc. or third-party contributors as
4+
* Copyright (c) 2011, Red Hat Inc. or third-party contributors as
55
* indicated by the @author tags or express copyright attribution
66
* statements applied by the authors. All third-party contributions are
77
* distributed under license by Red Hat Inc.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
/*
2+
* Hibernate, Relational Persistence for Idiomatic Java
3+
*
4+
* Copyright (c) 2011, Red Hat Inc. or third-party contributors as
5+
* indicated by the @author tags or express copyright attribution
6+
* statements applied by the authors. All third-party contributions are
7+
* distributed under license by Red Hat Inc.
8+
*
9+
* This copyrighted material is made available to anyone wishing to use, modify,
10+
* copy, or redistribute it subject to the terms and conditions of the GNU
11+
* Lesser General Public License, as published by the Free Software Foundation.
12+
*
13+
* This program is distributed in the hope that it will be useful,
14+
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15+
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
16+
* for more details.
17+
*
18+
* You should have received a copy of the GNU Lesser General Public License
19+
* along with this distribution; if not, write to:
20+
* Free Software Foundation, Inc.
21+
* 51 Franklin Street, Fifth Floor
22+
* Boston, MA 02110-1301 USA
23+
*/
24+
25+
package org.hibernate.metamodel.source.annotations.entity;
26+
27+
import javax.persistence.Entity;
28+
import javax.persistence.Id;
29+
import javax.persistence.Table;
30+
import javax.persistence.UniqueConstraint;
31+
32+
import org.junit.Test;
33+
34+
import org.hibernate.metamodel.binding.EntityBinding;
35+
import org.hibernate.metamodel.relational.Column;
36+
import org.hibernate.metamodel.relational.TableSpecification;
37+
import org.hibernate.metamodel.relational.UniqueKey;
38+
39+
import static junit.framework.Assert.assertEquals;
40+
import static junit.framework.Assert.assertNotNull;
41+
import static junit.framework.Assert.assertTrue;
42+
43+
/**
44+
* test for {@link javax.persistence.UniqueConstraint}
45+
*
46+
* @author Strong Liu
47+
*/
48+
public class UniqueConstraintBindingTests extends BaseAnnotationBindingTestCase {
49+
@Test
50+
public void testTableUniqueconstraints() {
51+
buildMetadataSources( TableWithUniqueConstraint.class );
52+
EntityBinding binding = getEntityBinding( TableWithUniqueConstraint.class );
53+
TableSpecification table = binding.getBaseTable();
54+
Iterable<UniqueKey> uniqueKeyIterable = table.getUniqueKeys();
55+
assertNotNull( uniqueKeyIterable );
56+
int i = 0;
57+
for ( UniqueKey key : uniqueKeyIterable ) {
58+
i++;
59+
assertEquals( "u1", key.getName() );
60+
assertTrue( table == key.getTable() );
61+
assertNotNull( key.getColumns() );
62+
int j = 0;
63+
for ( Column column : key.getColumns() ) {
64+
j++;
65+
66+
}
67+
assertEquals( 2, j );
68+
}
69+
assertEquals( 1, i );
70+
}
71+
72+
73+
@Entity
74+
@Table(uniqueConstraints = { @UniqueConstraint(name = "u1", columnNames = { "name", "age" }) })
75+
class TableWithUniqueConstraint {
76+
@Id
77+
int id;
78+
String name;
79+
int age;
80+
}
81+
}

0 commit comments

Comments
 (0)