7
7
import io .github .ngbsn .model .Table ;
8
8
import io .github .ngbsn .model .annotations .field .*;
9
9
import io .github .ngbsn .util .Util ;
10
- import org .apache .commons .text .WordUtils ;
11
10
12
11
import java .util .ArrayList ;
13
12
import java .util .HashSet ;
14
13
import java .util .List ;
15
14
import java .util .Optional ;
16
- import java .util .stream .Collectors ;
17
15
import java .util .stream .Stream ;
18
16
19
17
/**
@@ -111,12 +109,19 @@ private static void handleSingleForeignKey(final Table table, final ForeignKeyCo
111
109
private static void handleCompositeForeignKey (final Table table , final Table parentTable , final ForeignKeyConstraint foreignKeyConstraint ,
112
110
final Column parentTableField , final EmbeddableClass embeddableId , final List <Column > allPrimaryKeyColumns ) {
113
111
List <Column > listOfForeignKeyColumns = listOfForeignKeys (table , foreignKeyConstraint );
114
- //Case: Shared Composite Primary Key
115
- //If composite foreign key is inside the composite primary key, don't remove them from table.
116
- //This case assumes there is a primary composite key
117
- //Add a @MapsId annotation to the referenced table field
118
- if (embeddableId != null && new HashSet <>(allPrimaryKeyColumns ).containsAll (listOfForeignKeyColumns )) {
119
- handleCompositeForeignKeyInsideCompositePrimaryKey (table , parentTable , parentTableField , embeddableId , listOfForeignKeyColumns );
112
+ if (embeddableId != null && new HashSet <>(allPrimaryKeyColumns ).equals (new HashSet <>(listOfForeignKeyColumns ))){
113
+ //Case: Shared Composite Primary Key
114
+ //This case assumes there is a primary composite key
115
+ //If composite foreign key has same columns as composite primary key, don't remove them from table.
116
+ //Add a @MapsId annotation to the referenced table field
117
+ handleCompositeForeignKeySameAsCompositePrimaryKey (table , parentTable , parentTableField );
118
+ }
119
+ else if (embeddableId != null && new HashSet <>(allPrimaryKeyColumns ).containsAll (listOfForeignKeyColumns )) {
120
+ //Case: Shared Composite Primary Key
121
+ //This case assumes there is a primary composite key
122
+ //If composite foreign key is inside the composite primary key, don't remove them from table.
123
+ //Add a @MapsId annotation to the referenced table field
124
+ handleCompositeForeignKeyInsideCompositePrimaryKey (parentTable , parentTableField , embeddableId , listOfForeignKeyColumns );
120
125
} else {
121
126
//Case1: There is no Composite primary key
122
127
//TODO can part of Composite foreign key be a primary key. Is this applicable only to self referencing cases?
@@ -136,38 +141,40 @@ private static void handleCompositeForeignKey(final Table table, final Table par
136
141
parentTableField .getAnnotations ().add (JoinColumnsAnnotation .builder ().joinColumns (joinColumns ).build ().toString ());
137
142
}
138
143
139
- private static void handleCompositeForeignKeyInsideCompositePrimaryKey (final Table table , final Table parentTable , final Column parentTableField ,
144
+ private static void handleCompositeForeignKeySameAsCompositePrimaryKey (final Table table , final Table parentTable , final Column parentTableField ) {
145
+ //Reuse the parent table embeddedId class to create a field for the shared primary key
146
+ EmbeddableClass parentEmbeddedId = parentTable .getEmbeddedId ();
147
+ Column parentEmbeddedIdColumn = new Column ();
148
+ parentEmbeddedIdColumn .setType (parentTable .getClassName () + "." + parentEmbeddedId .getClassName ());
149
+ parentEmbeddedIdColumn .setFieldName (parentEmbeddedId .getFieldName ());
150
+ parentEmbeddedIdColumn .setEmbeddedId (true );
151
+ table .getColumns ().add (parentEmbeddedIdColumn );
152
+ //Remove EmbeddedID from child table
153
+ table .setEmbeddedId (null );
154
+
155
+ //Add @MapsId annotation, as the shared primary key is not set explicitly in this table, rather managed through parent primary key
156
+ parentTableField .getAnnotations ().add (MapsIdAnnotation .builder ().fieldName (parentEmbeddedIdColumn .getFieldName ()).build ().toString ());
157
+ }
158
+
159
+ private static void handleCompositeForeignKeyInsideCompositePrimaryKey (final Table parentTable , final Column parentTableField ,
140
160
final EmbeddableClass embeddableId , final List <Column > listOfForeignKeyColumns ) {
161
+ //remove all foreign key columns as they are tracked by the EmbeddedID field of parent
162
+ listOfForeignKeyColumns .forEach (column ->
163
+ embeddableId .getColumns ().remove (column )
164
+ );
165
+
166
+ //Reuse the parent table embeddedId class to create a field for the shared primary key
167
+ EmbeddableClass parentEmbeddedId = parentTable .getEmbeddedId ();
168
+ Column parentEmbeddedIdColumn = new Column ();
169
+ parentEmbeddedIdColumn .setType (parentTable .getClassName () + "." + parentEmbeddedId .getClassName ());
170
+ parentEmbeddedIdColumn .setFieldName (parentEmbeddedId .getFieldName ());
171
+ embeddableId .getColumns ().add (parentEmbeddedIdColumn );
141
172
142
- EmbeddableClass foreignCompositeKeyEmbedded = new EmbeddableClass (); //Create a new embeddable for this foreign composite key
143
- String embeddableName = listOfForeignKeyColumns .stream ().map (Column ::getFieldName ).collect (Collectors .joining ());
144
- foreignCompositeKeyEmbedded .setClassName (WordUtils .capitalize (embeddableName ));
145
- foreignCompositeKeyEmbedded .setFieldName (embeddableName );
146
- table .getEmbeddableClasses ().add (foreignCompositeKeyEmbedded ); //add new embeddable to the Table list of Embeddables
147
- listOfForeignKeyColumns .forEach (column -> {
148
- //Remove existing column annotations and add again with updatable=false, insertable=false.
149
- //This is necessary as the column is inserted/updated through foreign key
150
- column .getAnnotations ().removeIf (s -> s .contains ("@Column" ));
151
- column .getAnnotations ().add (ColumnAnnotation .builder ()
152
- .columnName (column .getColumnName ())
153
- .updatable (false )
154
- .insertable (false )
155
- .build ().toString ());
156
-
157
- //add the individual foreign keys columns to the newly created embeddable
158
- foreignCompositeKeyEmbedded .getColumns ().add (column );
159
- //Remove the individual foreign keys from EmbeddedId and add the newly created embeddable into EmbeddedId
160
- embeddableId .getColumns ().remove (column );
161
- });
162
- Column foreignCompositeField = new Column ();
163
- foreignCompositeField .setType (foreignCompositeKeyEmbedded .getClassName ());
164
- foreignCompositeField .setFieldName (foreignCompositeKeyEmbedded .getFieldName ());
165
- embeddableId .getColumns ().add (foreignCompositeField );
166
-
167
- if (embeddableId .getFieldName () != null )
168
- parentTableField .getAnnotations ().add (MapsIdAnnotation .builder ().fieldName (foreignCompositeField .getFieldName ()).build ().toString ());
173
+ //Add @MapsId annotation, as the shared primary key is not set explicitly in this table, rather managed through parent primary key
174
+ parentTableField .getAnnotations ().add (MapsIdAnnotation .builder ().fieldName (parentEmbeddedIdColumn .getFieldName ()).build ().toString ());
169
175
}
170
176
177
+
171
178
/**
172
179
* Convert column names in foreignKeyConstraint to List of Column models
173
180
* @param table table
0 commit comments