26
26
import java .util .Set ;
27
27
import java .util .stream .Collectors ;
28
28
import java .util .stream .Stream ;
29
+
29
30
import org .springframework .data .annotation .Id ;
30
31
import org .springframework .data .mapping .context .MappingContext ;
31
32
import org .springframework .data .relational .core .mapping .MappedCollection ;
34
35
import org .springframework .data .relational .core .mapping .RelationalPersistentProperty ;
35
36
import org .springframework .data .relational .core .sql .SqlIdentifier ;
36
37
import org .springframework .lang .Nullable ;
38
+ import org .springframework .util .Assert ;
37
39
38
40
/**
39
41
* Model class that contains Table/Column information that can be used to generate SQL for Schema generation.
40
42
*
41
43
* @author Kurt Niemi
44
+ * @author Evgenii Koba
42
45
* @since 3.2
43
46
*/
44
47
record Tables (List <Table > tables ) {
@@ -71,7 +74,7 @@ public static Tables from(Stream<? extends RelationalPersistentEntity<?>> persis
71
74
}
72
75
73
76
Column column = new Column (property .getColumnName ().getReference (), sqlTypeMapping .getColumnType (property ),
74
- sqlTypeMapping .isNullable (property ), identifierColumns .contains (property ));
77
+ sqlTypeMapping .isNullable (property ), identifierColumns .contains (property ));
75
78
table .columns ().add (column );
76
79
}
77
80
return table ;
@@ -92,34 +95,40 @@ public static Tables empty() {
92
95
private static void applyForeignKeyMetadata (List <Table > tables , List <ForeignKeyMetadata > foreignKeyMetadataList ) {
93
96
94
97
foreignKeyMetadataList .forEach (foreignKeyMetadata -> {
95
- Table table = tables .stream ().filter (t -> t .name ().equals (foreignKeyMetadata .tableName )).findAny ().get ();
98
+
99
+ Table table = tables .stream ().filter (t -> t .name ().equals (foreignKeyMetadata .tableName )).findAny ().orElseThrow ();
96
100
97
101
List <Column > parentIdColumns = collectParentIdentityColumns (foreignKeyMetadata , foreignKeyMetadataList , tables );
98
102
List <String > parentIdColumnNames = parentIdColumns .stream ().map (Column ::name ).toList ();
99
103
100
104
String foreignKeyName = getForeignKeyName (foreignKeyMetadata .parentTableName , parentIdColumnNames );
101
- if (parentIdColumnNames .size () == 1 ) {
102
- addIfAbsent (table .columns (), new Column (foreignKeyMetadata .referencingColumnName (), parentIdColumns .get (0 ).type (),
103
- false , table .getIdColumns ().isEmpty ()));
104
- if (foreignKeyMetadata .keyColumnName () != null ) {
105
- addIfAbsent (table .columns (), new Column (foreignKeyMetadata .keyColumnName (), foreignKeyMetadata .keyColumnType (),
106
- false , true ));
105
+ if (parentIdColumnNames .size () == 1 ) {
106
+
107
+ addIfAbsent (table .columns (), new Column (foreignKeyMetadata .referencingColumnName (),
108
+ parentIdColumns .get (0 ).type (), false , table .getIdColumns ().isEmpty ()));
109
+ if (foreignKeyMetadata .keyColumnName () != null ) {
110
+ addIfAbsent (table .columns (),
111
+ new Column (foreignKeyMetadata .keyColumnName (), foreignKeyMetadata .keyColumnType (), false , true ));
107
112
}
108
- addIfAbsent (table .foreignKeys (), new ForeignKey (foreignKeyName , foreignKeyMetadata .tableName (),
109
- List .of (foreignKeyMetadata .referencingColumnName ()), foreignKeyMetadata .parentTableName (), parentIdColumnNames ));
113
+ addIfAbsent (table .foreignKeys (),
114
+ new ForeignKey (foreignKeyName , foreignKeyMetadata .tableName (),
115
+ List .of (foreignKeyMetadata .referencingColumnName ()), foreignKeyMetadata .parentTableName (),
116
+ parentIdColumnNames ));
110
117
} else {
118
+
111
119
addIfAbsent (table .columns (), parentIdColumns .toArray (new Column [0 ]));
112
- addIfAbsent (table .columns (), new Column ( foreignKeyMetadata . keyColumnName (), foreignKeyMetadata . keyColumnType (),
113
- false , true ));
114
- addIfAbsent (table .foreignKeys (), new ForeignKey (foreignKeyName , foreignKeyMetadata .tableName (), parentIdColumnNames ,
115
- foreignKeyMetadata .parentTableName (), parentIdColumnNames ));
120
+ addIfAbsent (table .columns (),
121
+ new Column ( foreignKeyMetadata . keyColumnName (), foreignKeyMetadata . keyColumnType (), false , true ));
122
+ addIfAbsent (table .foreignKeys (), new ForeignKey (foreignKeyName , foreignKeyMetadata .tableName (),
123
+ parentIdColumnNames , foreignKeyMetadata .parentTableName (), parentIdColumnNames ));
116
124
}
117
125
118
126
});
119
127
}
120
128
121
- private static <E > void addIfAbsent (List <E > list , E ... elements ) {
122
- for (E element : elements ) {
129
+ private static <E > void addIfAbsent (List <E > list , E ... elements ) {
130
+
131
+ for (E element : elements ) {
123
132
if (!list .contains (element )) {
124
133
list .add (element );
125
134
}
@@ -137,26 +146,28 @@ private static List<Column> collectParentIdentityColumns(ForeignKeyMetadata chil
137
146
excludeTables .add (child .tableName ());
138
147
139
148
Table parentTable = findTableByName (tables , child .parentTableName ());
140
- ForeignKeyMetadata parentMetadata = findMetadataByTableName (foreignKeyMetadataList , child .parentTableName (), excludeTables );
149
+ ForeignKeyMetadata parentMetadata = findMetadataByTableName (foreignKeyMetadataList , child .parentTableName (),
150
+ excludeTables );
141
151
List <Column > parentIdColumns = parentTable .getIdColumns ();
142
152
143
153
if (!parentIdColumns .isEmpty ()) {
144
154
return new ArrayList <>(parentIdColumns );
145
- } else if (parentMetadata == null ) {
146
- //mustn't happen, probably wrong entity declaration
147
- return new ArrayList <>();
148
- } else {
149
- List <Column > parentParentIdColumns = collectParentIdentityColumns (parentMetadata , foreignKeyMetadataList , tables );
150
- if (parentParentIdColumns .size () == 1 ) {
151
- Column parentParentIdColumn = parentParentIdColumns .get (0 );
152
- Column withChangedName = new Column (parentMetadata .referencingColumnName , parentParentIdColumn .type (), false , true );
153
- parentParentIdColumns = new LinkedList <>(List .of (withChangedName ));
154
- }
155
- if (parentMetadata .keyColumnName () != null ) {
156
- parentParentIdColumns .add (new Column (parentMetadata .keyColumnName (), parentMetadata .keyColumnType (), false , true ));
157
- }
158
- return parentParentIdColumns ;
159
155
}
156
+
157
+ Assert .state (parentMetadata != null , "parentMetadata must not be null at this stage" );
158
+
159
+ List <Column > parentParentIdColumns = collectParentIdentityColumns (parentMetadata , foreignKeyMetadataList , tables );
160
+ if (parentParentIdColumns .size () == 1 ) {
161
+ Column parentParentIdColumn = parentParentIdColumns .get (0 );
162
+ Column withChangedName = new Column (parentMetadata .referencingColumnName , parentParentIdColumn .type (), false ,
163
+ true );
164
+ parentParentIdColumns = new LinkedList <>(List .of (withChangedName ));
165
+ }
166
+ if (parentMetadata .keyColumnName () != null ) {
167
+ parentParentIdColumns
168
+ .add (new Column (parentMetadata .keyColumnName (), parentMetadata .keyColumnType (), false , true ));
169
+ }
170
+ return parentParentIdColumns ;
160
171
}
161
172
162
173
@ Nullable
@@ -167,45 +178,40 @@ private static Table findTableByName(List<Table> tables, String tableName) {
167
178
@ Nullable
168
179
private static ForeignKeyMetadata findMetadataByTableName (List <ForeignKeyMetadata > metadata , String tableName ,
169
180
Set <String > excludeTables ) {
181
+
170
182
return metadata .stream ()
171
- .filter (m -> m .tableName ().equals (tableName ) && !excludeTables .contains (m .parentTableName ()))
172
- .findAny ()
183
+ .filter (m -> m .tableName ().equals (tableName ) && !excludeTables .contains (m .parentTableName ())).findAny ()
173
184
.orElse (null );
174
185
}
175
186
176
- private static ForeignKeyMetadata createForeignKeyMetadata (
177
- RelationalPersistentEntity <?> entity ,
187
+ private static ForeignKeyMetadata createForeignKeyMetadata (RelationalPersistentEntity <?> entity ,
178
188
RelationalPersistentProperty property ,
179
189
MappingContext <? extends RelationalPersistentEntity <?>, ? extends RelationalPersistentProperty > context ,
180
190
SqlTypeMapping sqlTypeMapping ) {
181
191
182
192
RelationalPersistentEntity childEntity = context .getRequiredPersistentEntity (property .getActualType ());
183
193
184
194
String referencedKeyColumnType = null ;
185
- if (property .isAnnotationPresent (MappedCollection .class )) {
195
+ if (property .isAnnotationPresent (MappedCollection .class )) {
186
196
if (property .getType () == List .class ) {
187
- referencedKeyColumnType = sqlTypeMapping .getColumnTypeByClass (Integer .class );
197
+ referencedKeyColumnType = sqlTypeMapping .getColumnType (Integer .class );
188
198
} else if (property .getType () == Map .class ) {
189
- referencedKeyColumnType = sqlTypeMapping .getColumnTypeByClass (property .getComponentType ());
199
+ referencedKeyColumnType = sqlTypeMapping .getColumnType (property .getComponentType ());
190
200
}
191
201
}
192
202
193
- return new ForeignKeyMetadata (
194
- childEntity .getTableName ().getReference (),
203
+ return new ForeignKeyMetadata (childEntity .getTableName ().getReference (),
195
204
property .getReverseColumnName (entity ).getReference (),
196
205
Optional .ofNullable (property .getKeyColumn ()).map (SqlIdentifier ::getReference ).orElse (null ),
197
- referencedKeyColumnType ,
198
- entity .getTableName ().getReference ()
199
- );
206
+ referencedKeyColumnType , entity .getTableName ().getReference ());
200
207
}
201
208
202
- //TODO should we place it in BasicRelationalPersistentProperty/BasicRelationalPersistentEntity and generate using NamingStrategy?
203
209
private static String getForeignKeyName (String referencedTableName , List <String > referencedColumnNames ) {
204
210
return String .format ("%s_%s_fk" , referencedTableName , String .join ("_" , referencedColumnNames ));
205
211
}
206
212
207
213
private record ForeignKeyMetadata (String tableName , String referencingColumnName , @ Nullable String keyColumnName ,
208
- @ Nullable String keyColumnType , String parentTableName ) {
214
+ @ Nullable String keyColumnType , String parentTableName ) {
209
215
210
216
}
211
217
}
0 commit comments