2626import java .util .Set ;
2727import java .util .stream .Collectors ;
2828import java .util .stream .Stream ;
29+
2930import org .springframework .data .annotation .Id ;
3031import org .springframework .data .mapping .context .MappingContext ;
3132import org .springframework .data .relational .core .mapping .MappedCollection ;
3435import org .springframework .data .relational .core .mapping .RelationalPersistentProperty ;
3536import org .springframework .data .relational .core .sql .SqlIdentifier ;
3637import org .springframework .lang .Nullable ;
38+ import org .springframework .util .Assert ;
3739
3840/**
3941 * Model class that contains Table/Column information that can be used to generate SQL for Schema generation.
4042 *
4143 * @author Kurt Niemi
44+ * @author Evgenii Koba
4245 * @since 3.2
4346 */
4447record Tables (List <Table > tables ) {
@@ -71,7 +74,7 @@ public static Tables from(Stream<? extends RelationalPersistentEntity<?>> persis
7174 }
7275
7376 Column column = new Column (property .getColumnName ().getReference (), sqlTypeMapping .getColumnType (property ),
74- sqlTypeMapping .isNullable (property ), identifierColumns .contains (property ));
77+ sqlTypeMapping .isNullable (property ), identifierColumns .contains (property ));
7578 table .columns ().add (column );
7679 }
7780 return table ;
@@ -92,34 +95,40 @@ public static Tables empty() {
9295 private static void applyForeignKeyMetadata (List <Table > tables , List <ForeignKeyMetadata > foreignKeyMetadataList ) {
9396
9497 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 ();
96100
97101 List <Column > parentIdColumns = collectParentIdentityColumns (foreignKeyMetadata , foreignKeyMetadataList , tables );
98102 List <String > parentIdColumnNames = parentIdColumns .stream ().map (Column ::name ).toList ();
99103
100104 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 ));
107112 }
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 ));
110117 } else {
118+
111119 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 ));
116124 }
117125
118126 });
119127 }
120128
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 ) {
123132 if (!list .contains (element )) {
124133 list .add (element );
125134 }
@@ -137,26 +146,28 @@ private static List<Column> collectParentIdentityColumns(ForeignKeyMetadata chil
137146 excludeTables .add (child .tableName ());
138147
139148 Table parentTable = findTableByName (tables , child .parentTableName ());
140- ForeignKeyMetadata parentMetadata = findMetadataByTableName (foreignKeyMetadataList , child .parentTableName (), excludeTables );
149+ ForeignKeyMetadata parentMetadata = findMetadataByTableName (foreignKeyMetadataList , child .parentTableName (),
150+ excludeTables );
141151 List <Column > parentIdColumns = parentTable .getIdColumns ();
142152
143153 if (!parentIdColumns .isEmpty ()) {
144154 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 ;
159155 }
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 ;
160171 }
161172
162173 @ Nullable
@@ -167,45 +178,40 @@ private static Table findTableByName(List<Table> tables, String tableName) {
167178 @ Nullable
168179 private static ForeignKeyMetadata findMetadataByTableName (List <ForeignKeyMetadata > metadata , String tableName ,
169180 Set <String > excludeTables ) {
181+
170182 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 ()
173184 .orElse (null );
174185 }
175186
176- private static ForeignKeyMetadata createForeignKeyMetadata (
177- RelationalPersistentEntity <?> entity ,
187+ private static ForeignKeyMetadata createForeignKeyMetadata (RelationalPersistentEntity <?> entity ,
178188 RelationalPersistentProperty property ,
179189 MappingContext <? extends RelationalPersistentEntity <?>, ? extends RelationalPersistentProperty > context ,
180190 SqlTypeMapping sqlTypeMapping ) {
181191
182192 RelationalPersistentEntity childEntity = context .getRequiredPersistentEntity (property .getActualType ());
183193
184194 String referencedKeyColumnType = null ;
185- if (property .isAnnotationPresent (MappedCollection .class )) {
195+ if (property .isAnnotationPresent (MappedCollection .class )) {
186196 if (property .getType () == List .class ) {
187- referencedKeyColumnType = sqlTypeMapping .getColumnTypeByClass (Integer .class );
197+ referencedKeyColumnType = sqlTypeMapping .getColumnType (Integer .class );
188198 } else if (property .getType () == Map .class ) {
189- referencedKeyColumnType = sqlTypeMapping .getColumnTypeByClass (property .getComponentType ());
199+ referencedKeyColumnType = sqlTypeMapping .getColumnType (property .getComponentType ());
190200 }
191201 }
192202
193- return new ForeignKeyMetadata (
194- childEntity .getTableName ().getReference (),
203+ return new ForeignKeyMetadata (childEntity .getTableName ().getReference (),
195204 property .getReverseColumnName (entity ).getReference (),
196205 Optional .ofNullable (property .getKeyColumn ()).map (SqlIdentifier ::getReference ).orElse (null ),
197- referencedKeyColumnType ,
198- entity .getTableName ().getReference ()
199- );
206+ referencedKeyColumnType , entity .getTableName ().getReference ());
200207 }
201208
202- //TODO should we place it in BasicRelationalPersistentProperty/BasicRelationalPersistentEntity and generate using NamingStrategy?
203209 private static String getForeignKeyName (String referencedTableName , List <String > referencedColumnNames ) {
204210 return String .format ("%s_%s_fk" , referencedTableName , String .join ("_" , referencedColumnNames ));
205211 }
206212
207213 private record ForeignKeyMetadata (String tableName , String referencingColumnName , @ Nullable String keyColumnName ,
208- @ Nullable String keyColumnType , String parentTableName ) {
214+ @ Nullable String keyColumnType , String parentTableName ) {
209215
210216 }
211217}
0 commit comments