Skip to content

Commit fd1accf

Browse files
committed
introduce @DefaultSchema
to allow setting the schema at the package or outer class level
1 parent e1e16a5 commit fd1accf

File tree

4 files changed

+110
-6
lines changed

4 files changed

+110
-6
lines changed
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
/*
2+
* Hibernate, Relational Persistence for Idiomatic Java
3+
*
4+
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
5+
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
6+
*/
7+
package org.hibernate.annotations;
8+
9+
import org.hibernate.Incubating;
10+
11+
import java.lang.annotation.Retention;
12+
import java.lang.annotation.Target;
13+
14+
import static java.lang.annotation.ElementType.PACKAGE;
15+
import static java.lang.annotation.ElementType.TYPE;
16+
import static java.lang.annotation.RetentionPolicy.RUNTIME;
17+
18+
/**
19+
* Specifies a default schema for all table mappings occurring within
20+
* the scope of the annotated package or type, overriding the effect of
21+
* {@value org.hibernate.cfg.AvailableSettings#DEFAULT_SCHEMA} and/or
22+
* {@value org.hibernate.cfg.AvailableSettings#DEFAULT_CATALOG} if
23+
* either of these configuration properties is specified.
24+
* <p>
25+
* The default schema specified by this annotation is ignored if a
26+
* table mapping explicitly specifies a
27+
* {@linkplain jakarta.persistence.Table#schema() schema} or
28+
* {@linkplain jakarta.persistence.Table#catalog() catalog}.
29+
*
30+
* @author Gavin King
31+
*/
32+
@Incubating
33+
@Target({TYPE,PACKAGE})
34+
@Retention(RUNTIME)
35+
public @interface DefaultSchema {
36+
/**
37+
* A schema to use when no schema is explicitly specified using
38+
* {@link jakarta.persistence.Table#schema()}.
39+
*/
40+
String schema() default "";
41+
/**
42+
* A catalog to use when no schema is explicitly specified using
43+
* {@link jakarta.persistence.Table#catalog()}.
44+
*/
45+
String catalog() default "";
46+
}

hibernate-core/src/main/java/org/hibernate/cfg/AnnotationBinder.java

Lines changed: 55 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
import org.hibernate.annotations.Columns;
4141
import org.hibernate.annotations.Comment;
4242
import org.hibernate.annotations.DialectOverride.OverridesAnnotation;
43+
import org.hibernate.annotations.DefaultSchema;
4344
import org.hibernate.annotations.DiscriminatorFormula;
4445
import org.hibernate.annotations.DiscriminatorOptions;
4546
import org.hibernate.annotations.EmbeddableInstantiatorRegistration;
@@ -595,9 +596,9 @@ public static void bindClass(
595596
bindQueries( clazzToProcess, context );
596597
bindFilterDefs( clazzToProcess, context );
597598

598-
String schema = "";
599-
String table = ""; //might be no @Table annotation on the annotated class
600-
String catalog = "";
599+
String schema;
600+
String catalog;
601+
String table;
601602
List<UniqueConstraintHolder> uniqueConstraints = new ArrayList<>();
602603
jakarta.persistence.Table tabAnn = null;
603604
if ( clazzToProcess.isAnnotationPresent( jakarta.persistence.Table.class ) ) {
@@ -607,6 +608,19 @@ public static void bindClass(
607608
catalog = tabAnn.catalog();
608609
uniqueConstraints = TableBinder.buildUniqueConstraintHolders( tabAnn.uniqueConstraints() );
609610
}
611+
else {
612+
//might be no @Table annotation on the annotated class
613+
schema = "";
614+
catalog = "";
615+
table = "";
616+
}
617+
618+
if ( schema.isEmpty() ) {
619+
schema = defaultSchema( clazzToProcess );
620+
}
621+
if ( catalog.isEmpty() ) {
622+
catalog = defaultCatalog( clazzToProcess );
623+
}
610624

611625
AnnotatedJoinColumn[] inheritanceJoinedColumns = makeInheritanceJoinColumns(
612626
clazzToProcess,
@@ -899,6 +913,36 @@ public static <T extends Annotation> T getOverridableAnnotation(
899913
return element.getAnnotation( annotationType );
900914
}
901915

916+
public static String defaultSchema(XClass clazzToProcess) {
917+
XAnnotatedElement annotatedElement = clazzToProcess;
918+
while (true) {
919+
if ( annotatedElement.isAnnotationPresent(DefaultSchema.class) ) {
920+
return annotatedElement.getAnnotation(DefaultSchema.class).schema();
921+
}
922+
else if ( annotatedElement instanceof XClass ) {
923+
annotatedElement = ((XClass) annotatedElement).getContainingElement();
924+
}
925+
else {
926+
return "";
927+
}
928+
}
929+
}
930+
931+
public static String defaultCatalog(XClass clazzToProcess) {
932+
XAnnotatedElement annotatedElement = clazzToProcess;
933+
while (true) {
934+
if ( annotatedElement.isAnnotationPresent(DefaultSchema.class) ) {
935+
return annotatedElement.getAnnotation(DefaultSchema.class).catalog();
936+
}
937+
else if ( annotatedElement instanceof XClass ) {
938+
annotatedElement = ((XClass) annotatedElement).getContainingElement();
939+
}
940+
else {
941+
return "";
942+
}
943+
}
944+
}
945+
902946
private static void handleTypeDescriptorRegistrations(XAnnotatedElement annotatedElement, MetadataBuildingContext context) {
903947
final ManagedBeanRegistry managedBeanRegistry = context.getBootstrapContext()
904948
.getServiceRegistry()
@@ -2707,9 +2751,15 @@ private static void bindJoinedTableAssociation(
27072751
if ( !BinderHelper.isEmptyAnnotationValue( schema ) ) {
27082752
associationTableBinder.setSchema( schema );
27092753
}
2754+
else {
2755+
associationTableBinder.setSchema( defaultSchema( property.getDeclaringClass() ) );
2756+
}
27102757
if ( !BinderHelper.isEmptyAnnotationValue( catalog ) ) {
27112758
associationTableBinder.setCatalog( catalog );
27122759
}
2760+
else {
2761+
associationTableBinder.setCatalog( defaultCatalog( property.getDeclaringClass() ) );
2762+
}
27132763
if ( !BinderHelper.isEmptyAnnotationValue( tableName ) ) {
27142764
associationTableBinder.setName( tableName );
27152765
}
@@ -2722,6 +2772,8 @@ private static void bindJoinedTableAssociation(
27222772
else {
27232773
annJoins = null;
27242774
annInverseJoins = null;
2775+
associationTableBinder.setSchema( defaultSchema( property.getDeclaringClass() ) );
2776+
associationTableBinder.setCatalog( defaultCatalog( property.getDeclaringClass() ) );
27252777
}
27262778
AnnotatedJoinColumn[] joinColumns = AnnotatedJoinColumn.buildJoinTableJoinColumns(
27272779
annJoins,

hibernate-core/src/main/java/org/hibernate/cfg/AvailableSettings.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010

1111
import org.hibernate.HibernateException;
1212
import org.hibernate.query.NativeQuery;
13-
import org.hibernate.query.Query;
1413
import org.hibernate.Transaction;
1514
import org.hibernate.boot.MetadataBuilder;
1615
import org.hibernate.boot.registry.classloading.internal.TcclLookupPrecedence;

hibernate-core/src/main/java/org/hibernate/cfg/annotations/EntityBinder.java

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1056,8 +1056,8 @@ private Join addJoin(
10561056
Join join = new Join();
10571057
join.setPersistentClass( persistentClass );
10581058

1059-
final String schema;
1060-
final String catalog;
1059+
String schema;
1060+
String catalog;
10611061
final Object joinColumns;
10621062
final List<UniqueConstraintHolder> uniqueConstraintHolders;
10631063

@@ -1096,6 +1096,13 @@ else if ( joinTable != null ) {
10961096
throw new AssertionFailure( "Both JoinTable and SecondaryTable are null" );
10971097
}
10981098

1099+
if ( schema.isEmpty() ) {
1100+
schema = AnnotationBinder.defaultSchema( annotatedClass );
1101+
}
1102+
if ( catalog.isEmpty() ) {
1103+
catalog = AnnotationBinder.defaultCatalog( annotatedClass );
1104+
}
1105+
10991106
final Table table = TableBinder.buildAndFillTable(
11001107
schema,
11011108
catalog,

0 commit comments

Comments
 (0)