Skip to content

Commit 92bbe51

Browse files
dreab8sebersole
authored andcommitted
HHH-18054 Support for JPA 3.2 @CheckConstraint
1 parent 9bcfcdd commit 92bbe51

File tree

24 files changed

+789
-6
lines changed

24 files changed

+789
-6
lines changed

hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/MySQLLegacyDialect.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@
4141
import org.hibernate.exception.spi.TemplatedViolatedConstraintNameExtractor;
4242
import org.hibernate.exception.spi.ViolatedConstraintNameExtractor;
4343
import org.hibernate.internal.util.JdbcExceptionHelper;
44+
import org.hibernate.internal.util.StringHelper;
45+
import org.hibernate.mapping.CheckConstraint;
4446
import org.hibernate.metamodel.mapping.EntityMappingType;
4547
import org.hibernate.metamodel.spi.RuntimeModelCreationContext;
4648
import org.hibernate.query.sqm.CastType;
@@ -1429,4 +1431,11 @@ public boolean supportsFromClauseInUpdate() {
14291431
return true;
14301432
}
14311433

1434+
@Override
1435+
public String appendCheckConstraintOptions(CheckConstraint checkConstraint, String sqlCheckConstraint) {
1436+
if ( StringHelper.isNotEmpty( checkConstraint.getOptions() ) ) {
1437+
return sqlCheckConstraint + " " + checkConstraint.getOptions();
1438+
}
1439+
return sqlCheckConstraint;
1440+
}
14321441
}

hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/OracleLegacyDialect.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@
6868
import org.hibernate.exception.spi.ViolatedConstraintNameExtractor;
6969
import org.hibernate.internal.util.JdbcExceptionHelper;
7070
import org.hibernate.internal.util.StringHelper;
71+
import org.hibernate.mapping.CheckConstraint;
7172
import org.hibernate.mapping.UserDefinedType;
7273
import org.hibernate.metamodel.mapping.EntityMappingType;
7374
import org.hibernate.metamodel.spi.RuntimeModelCreationContext;
@@ -1576,4 +1577,12 @@ public boolean useInputStreamToInsertBlob() {
15761577
return false;
15771578
}
15781579

1580+
1581+
@Override
1582+
public String appendCheckConstraintOptions(CheckConstraint checkConstraint, String sqlCheckConstraint) {
1583+
if ( StringHelper.isNotEmpty( checkConstraint.getOptions() ) ) {
1584+
return sqlCheckConstraint + " " + checkConstraint.getOptions();
1585+
}
1586+
return sqlCheckConstraint;
1587+
}
15791588
}

hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/SQLServerLegacyDialect.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@
4949
import org.hibernate.exception.spi.TemplatedViolatedConstraintNameExtractor;
5050
import org.hibernate.exception.spi.ViolatedConstraintNameExtractor;
5151
import org.hibernate.internal.util.JdbcExceptionHelper;
52+
import org.hibernate.internal.util.StringHelper;
53+
import org.hibernate.mapping.CheckConstraint;
5254
import org.hibernate.mapping.Column;
5355
import org.hibernate.query.sqm.CastType;
5456
import org.hibernate.query.sqm.FetchClauseType;
@@ -1165,4 +1167,21 @@ public DmlTargetColumnQualifierSupport getDmlTargetColumnQualifierSupport() {
11651167
public boolean supportsFromClauseInUpdate() {
11661168
return true;
11671169
}
1170+
1171+
@Override
1172+
public String getCheckConstraintString(CheckConstraint checkConstraint) {
1173+
final String constraintName = checkConstraint.getName();
1174+
return constraintName == null
1175+
?
1176+
" check " + getCheckConstraintOptions( checkConstraint ) + "(" + checkConstraint.getConstraint() + ")"
1177+
:
1178+
" constraint " + constraintName + " check " + getCheckConstraintOptions( checkConstraint ) + "(" + checkConstraint.getConstraint() + ")";
1179+
}
1180+
1181+
private String getCheckConstraintOptions(CheckConstraint checkConstraint) {
1182+
if ( StringHelper.isNotEmpty( checkConstraint.getOptions() ) ) {
1183+
return checkConstraint.getOptions() + " ";
1184+
}
1185+
return "";
1186+
}
11681187
}

hibernate-core/src/main/java/org/hibernate/boot/model/internal/AnnotatedColumn.java

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
import org.hibernate.boot.spi.PropertyData;
3131
import org.hibernate.internal.CoreMessageLogger;
3232
import org.hibernate.internal.util.StringHelper;
33+
import org.hibernate.internal.util.collections.CollectionHelper;
3334
import org.hibernate.mapping.AggregateColumn;
3435
import org.hibernate.mapping.CheckConstraint;
3536
import org.hibernate.mapping.Column;
@@ -213,6 +214,10 @@ public void addCheckConstraint(String name, String constraint) {
213214
checkConstraints.add( new CheckConstraint( name, constraint ) );
214215
}
215216

217+
public void addCheckConstraint(String name, String constraint, String options) {
218+
checkConstraints.add( new CheckConstraint( name, constraint, options ) );
219+
}
220+
216221
// public String getComment() {
217222
// return comment;
218223
// }
@@ -800,6 +805,7 @@ private static AnnotatedColumn buildColumn(
800805
annotatedColumn.setParent( parent );
801806
annotatedColumn.applyColumnDefault( inferredData, numberOfColumns );
802807
annotatedColumn.applyGeneratedAs( inferredData, numberOfColumns );
808+
annotatedColumn.applyColumnCheckConstraint( column );
803809
annotatedColumn.applyCheckConstraint( inferredData, numberOfColumns );
804810
annotatedColumn.extractDataFromPropertyData( propertyHolder, inferredData );
805811
annotatedColumn.bind();
@@ -873,7 +879,23 @@ void applyGeneratedAs(PropertyData inferredData, int length) {
873879
}
874880
}
875881

876-
private void applyCheckConstraint(PropertyData inferredData, int length) {
882+
private void applyColumnCheckConstraint(AnnotationUsage<jakarta.persistence.Column> column) {
883+
applyCheckConstraints( column.findAttributeValue( "check" ) );
884+
}
885+
886+
void applyCheckConstraints(List<AnnotationUsage<jakarta.persistence.CheckConstraint>> checkConstraintAnnotationUsages) {
887+
if ( CollectionHelper.isNotEmpty( checkConstraintAnnotationUsages ) ) {
888+
for ( AnnotationUsage<jakarta.persistence.CheckConstraint> checkConstraintAnnotationUsage : checkConstraintAnnotationUsages ) {
889+
addCheckConstraint(
890+
checkConstraintAnnotationUsage.getString( "name" ),
891+
checkConstraintAnnotationUsage.getString( "constraint" ),
892+
checkConstraintAnnotationUsage.getString( "options" )
893+
);
894+
}
895+
}
896+
}
897+
898+
void applyCheckConstraint(PropertyData inferredData, int length) {
877899
final MemberDetails attributeMember = inferredData.getAttributeMember();
878900
if ( attributeMember != null ) {
879901
// if there are multiple annotations, they're not overrideable

hibernate-core/src/main/java/org/hibernate/boot/model/internal/AnnotatedJoinColumn.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,7 @@ public void applyJoinAnnotation(AnnotationUsage<JoinColumn> joinColumn, String d
195195
setInsertable( joinColumn.getBoolean( "insertable" ) );
196196
setUpdatable( joinColumn.getBoolean( "updatable" ) );
197197
setReferencedColumn( joinColumn.getString( "referencedColumnName" ) );
198+
applyColumnCheckConstraint( joinColumn );
198199

199200
final String table = joinColumn.getString( "table" );
200201
if ( table.isEmpty() ) {
@@ -516,4 +517,8 @@ public void setParent(AnnotatedColumns parent) {
516517
public void setParent(AnnotatedJoinColumns parent) {
517518
super.setParent( parent );
518519
}
520+
521+
private void applyColumnCheckConstraint(AnnotationUsage<jakarta.persistence.JoinColumn> column) {
522+
applyCheckConstraints( column.findAttributeValue( "check" ) );
523+
}
519524
}

hibernate-core/src/main/java/org/hibernate/boot/model/internal/CollectionBinder.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2583,6 +2583,11 @@ private void handleCheckConstraints(Table collectionTable) {
25832583
property.forEachAnnotationUsage( Check.class, (usage) -> {
25842584
addCheckToCollection( collectionTable, usage );
25852585
} );
2586+
property.forEachAnnotationUsage(
2587+
jakarta.persistence.JoinTable.class,
2588+
(usage) ->
2589+
TableBinder.addTableCheck( collectionTable, usage.findAttributeValue( "check" ) )
2590+
);
25862591
}
25872592

25882593
private static void addCheckToCollection(Table collectionTable, AnnotationUsage<Check> check) {

hibernate-core/src/main/java/org/hibernate/boot/model/internal/EntityBinder.java

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -447,7 +447,9 @@ private void processComplementaryTableDefinitions() {
447447

448448
final AnnotationUsage<jakarta.persistence.Table> jpaTableUsage = annotatedClass.getAnnotationUsage( jakarta.persistence.Table.class );
449449
if ( jpaTableUsage != null ) {
450-
TableBinder.addJpaIndexes( persistentClass.getTable(), jpaTableUsage.getList( "indexes" ), context );
450+
final Table table = persistentClass.getTable();
451+
TableBinder.addJpaIndexes( table, jpaTableUsage.getList( "indexes" ), context );
452+
TableBinder.addTableCheck( table, jpaTableUsage.findAttributeValue( "check" ) );
451453
}
452454

453455
final InFlightMetadataCollector.EntityTableXref entityTableXref = context
@@ -2162,7 +2164,7 @@ private <T extends Annotation,R extends Annotation> AnnotationUsage<T> findMatch
21622164

21632165
//Used for @*ToMany @JoinTable
21642166
public Join addJoinTable(AnnotationUsage<JoinTable> joinTable, PropertyHolder holder, boolean noDelayInPkColumnCreation) {
2165-
return addJoin(
2167+
final Join join = addJoin(
21662168
holder,
21672169
noDelayInPkColumnCreation,
21682170
false,
@@ -2172,6 +2174,8 @@ public Join addJoinTable(AnnotationUsage<JoinTable> joinTable, PropertyHolder ho
21722174
joinTable.getList( "joinColumns" ),
21732175
joinTable.getList( "uniqueConstraints" )
21742176
);
2177+
TableBinder.addTableCheck( join.getTable(), joinTable.findAttributeValue( "check" ));
2178+
return join;
21752179
}
21762180

21772181
public Join addSecondaryTable(AnnotationUsage<SecondaryTable> secondaryTable, PropertyHolder holder, boolean noDelayInPkColumnCreation) {
@@ -2187,6 +2191,7 @@ public Join addSecondaryTable(AnnotationUsage<SecondaryTable> secondaryTable, Pr
21872191
);
21882192
final Table table = join.getTable();
21892193
new IndexBinder( context ).bindIndexes( table, secondaryTable.getList( "indexes" ) );
2194+
TableBinder.addTableCheck( table, secondaryTable.findAttributeValue( "check" ));
21902195
return join;
21912196
}
21922197

hibernate-core/src/main/java/org/hibernate/boot/model/internal/TableBinder.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@
2323
import org.hibernate.dialect.Dialect;
2424
import org.hibernate.internal.CoreMessageLogger;
2525
import org.hibernate.mapping.Any;
26+
import org.hibernate.internal.util.collections.CollectionHelper;
27+
import org.hibernate.mapping.CheckConstraint;
2628
import org.hibernate.mapping.Collection;
2729
import org.hibernate.mapping.Column;
2830
import org.hibernate.mapping.Component;
@@ -870,6 +872,22 @@ static void addJpaIndexes(
870872
new IndexBinder( context ).bindIndexes( table, indexes );
871873
}
872874

875+
static void addTableCheck(
876+
Table table,
877+
List<AnnotationUsage<jakarta.persistence.CheckConstraint>> checkConstraintAnnotationUsages) {
878+
if ( CollectionHelper.isNotEmpty( checkConstraintAnnotationUsages ) ) {
879+
for ( AnnotationUsage<jakarta.persistence.CheckConstraint> checkConstraintAnnotationUsage : checkConstraintAnnotationUsages ) {
880+
table.addCheck(
881+
new CheckConstraint(
882+
checkConstraintAnnotationUsage.getString( "name" ),
883+
checkConstraintAnnotationUsage.getString( "constraint" ),
884+
checkConstraintAnnotationUsage.getString( "options" )
885+
)
886+
);
887+
}
888+
}
889+
}
890+
873891
public void setDefaultName(
874892
String ownerClassName,
875893
String ownerEntity,

hibernate-core/src/main/java/org/hibernate/dialect/Dialect.java

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@
109109
import org.hibernate.internal.util.StringHelper;
110110
import org.hibernate.internal.util.collections.ArrayHelper;
111111
import org.hibernate.loader.ast.spi.MultiKeyLoadSizingStrategy;
112+
import org.hibernate.mapping.CheckConstraint;
112113
import org.hibernate.mapping.Column;
113114
import org.hibernate.mapping.Constraint;
114115
import org.hibernate.mapping.ForeignKey;
@@ -5626,4 +5627,30 @@ public FunctionalDependencyAnalysisSupport getFunctionalDependencyAnalysisSuppor
56265627
return FunctionalDependencyAnalysisSupportImpl.NONE;
56275628
}
56285629

5630+
/**
5631+
* Render a SQL check condition for {@link CheckConstraint}
5632+
*
5633+
* @return a SQL expression representing the {@link CheckConstraint}
5634+
*/
5635+
public String getCheckConstraintString(CheckConstraint checkConstraint) {
5636+
final String constraintName = checkConstraint.getName();
5637+
String constraint = constraintName == null
5638+
? " check (" + checkConstraint.getConstraint() + ")"
5639+
: " constraint " + constraintName + " check (" + checkConstraint.getConstraint() + ")";
5640+
return appendCheckConstraintOptions( checkConstraint, constraint );
5641+
}
5642+
5643+
/**
5644+
* Append the {@link CheckConstraint} options to SQL check sqlCheckConstraint
5645+
*
5646+
* @param checkConstraint an instance of {@link CheckConstraint}
5647+
* @param sqlCheckConstraint the SQL to append the {@link CheckConstraint} options
5648+
*
5649+
* @return a SQL expression
5650+
*/
5651+
public String appendCheckConstraintOptions(CheckConstraint checkConstraint, String sqlCheckConstraint) {
5652+
return sqlCheckConstraint;
5653+
}
5654+
5655+
56295656
}

hibernate-core/src/main/java/org/hibernate/dialect/MySQLDialect.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@
4747
import org.hibernate.exception.spi.TemplatedViolatedConstraintNameExtractor;
4848
import org.hibernate.exception.spi.ViolatedConstraintNameExtractor;
4949
import org.hibernate.internal.util.JdbcExceptionHelper;
50+
import org.hibernate.internal.util.StringHelper;
51+
import org.hibernate.mapping.CheckConstraint;
5052
import org.hibernate.metamodel.mapping.EntityMappingType;
5153
import org.hibernate.metamodel.spi.RuntimeModelCreationContext;
5254
import org.hibernate.query.sqm.CastType;
@@ -1571,4 +1573,12 @@ public DmlTargetColumnQualifierSupport getDmlTargetColumnQualifierSupport() {
15711573
public boolean supportsFromClauseInUpdate() {
15721574
return true;
15731575
}
1576+
1577+
@Override
1578+
public String appendCheckConstraintOptions(CheckConstraint checkConstraint, String sqlCheckConstraint) {
1579+
if ( StringHelper.isNotEmpty( checkConstraint.getOptions() ) ) {
1580+
return sqlCheckConstraint + " " + checkConstraint.getOptions();
1581+
}
1582+
return sqlCheckConstraint;
1583+
}
15741584
}

0 commit comments

Comments
 (0)