Skip to content

Commit bb57397

Browse files
committed
1) Use Generator.IDENTITY instead of Generator.AUTO in template 2) Add logic for setting insertable and updatable to false 3) Handle ALTER STATEMENTS for ADD COLUMN and DROP COLUMN
1 parent 7fc71cb commit bb57397

File tree

9 files changed

+85
-45
lines changed

9 files changed

+85
-45
lines changed

pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,7 @@
181181
</descriptors>
182182
<archive>
183183
<manifest>
184-
<mainClass>io.github.ngbsn.generator.JPACodeGenerator</mainClass>
184+
<mainClass>io.github.ngbsn.generator.code.JPACodeGenerator</mainClass>
185185
</manifest>
186186
</archive>
187187
</configuration>

src/main/java/io/github/ngbsn/generator/AssociationMappingsGenerator.java renamed to src/main/java/io/github/ngbsn/generator/associations/AssociationMappingsGenerator.java

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
package io.github.ngbsn.generator;
1+
package io.github.ngbsn.generator.associations;
22

3+
import io.github.ngbsn.generator.models.ModelGenerator;
34
import io.github.ngbsn.model.Column;
45
import io.github.ngbsn.model.ForeignKeyConstraint;
56
import io.github.ngbsn.model.Table;
@@ -9,12 +10,12 @@
910
import java.util.Map;
1011
import java.util.Optional;
1112

12-
import static io.github.ngbsn.generator.OneToManyMappingsGenerator.addBiDirectionalMappings;
13+
import static io.github.ngbsn.generator.associations.OneToManyMappingsGenerator.addBiDirectionalMappings;
1314

1415
/**
1516
* Generate both UniDirectional and BiDirectional association mappings for all tables
1617
*/
17-
class AssociationMappingsGenerator {
18+
public class AssociationMappingsGenerator {
1819

1920

2021
private AssociationMappingsGenerator() {
@@ -23,7 +24,7 @@ private AssociationMappingsGenerator() {
2324
/**
2425
* Generate both UniDirectional and BiDirectional association mappings for all tables
2526
*/
26-
static void generateMappings() {
27+
public static void generateMappings() {
2728
Iterator<Map.Entry<String, Table>> it = ModelGenerator.getTablesMap().entrySet().iterator();
2829
while (it.hasNext()) {
2930
Map.Entry<String, Table> item = it.next();

src/main/java/io/github/ngbsn/generator/ManyToManyMappingsGenerator.java renamed to src/main/java/io/github/ngbsn/generator/associations/ManyToManyMappingsGenerator.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
package io.github.ngbsn.generator;
1+
package io.github.ngbsn.generator.associations;
22

3+
import io.github.ngbsn.generator.models.ModelGenerator;
34
import io.github.ngbsn.model.Column;
45
import io.github.ngbsn.model.ForeignKeyConstraint;
56
import io.github.ngbsn.model.Table;
@@ -14,7 +15,7 @@
1415
/**
1516
* Generate BiDirectional Mappings (many-to-many) for a specific table
1617
*/
17-
class ManyToManyMappingsGenerator {
18+
public class ManyToManyMappingsGenerator {
1819

1920
private ManyToManyMappingsGenerator() {
2021
}
@@ -25,7 +26,7 @@ private ManyToManyMappingsGenerator() {
2526
* @param table The table to be processed
2627
* @param foreignKeyConstraintList List of generated foreignKeyConstraintList models
2728
*/
28-
static void addManyToManyMappings(final Table table, final List<ForeignKeyConstraint> foreignKeyConstraintList) {
29+
public static void addManyToManyMappings(final Table table, final List<ForeignKeyConstraint> foreignKeyConstraintList) {
2930
Table table1 = ModelGenerator.getTablesMap().get(foreignKeyConstraintList.get(0).getReferencedTableName().replaceAll("[\"']", ""));
3031
Table table2 = ModelGenerator.getTablesMap().get(foreignKeyConstraintList.get(1).getReferencedTableName().replaceAll("[\"']", ""));
3132

src/main/java/io/github/ngbsn/generator/OneToManyMappingsGenerator.java renamed to src/main/java/io/github/ngbsn/generator/associations/OneToManyMappingsGenerator.java

Lines changed: 31 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
package io.github.ngbsn.generator;
1+
package io.github.ngbsn.generator.associations;
22

3+
import io.github.ngbsn.generator.models.ModelGenerator;
34
import io.github.ngbsn.model.Column;
45
import io.github.ngbsn.model.EmbeddableClass;
56
import io.github.ngbsn.model.ForeignKeyConstraint;
@@ -30,7 +31,7 @@ private OneToManyMappingsGenerator() {
3031
* @param table Table model
3132
* @param foreignKeyConstraint ForeignKeyConstraint model
3233
*/
33-
static void addBiDirectionalMappings(final Table table, final ForeignKeyConstraint foreignKeyConstraint) {
34+
public static void addBiDirectionalMappings(final Table table, final ForeignKeyConstraint foreignKeyConstraint) {
3435
Table parentTable = ModelGenerator.getTablesMap().get(foreignKeyConstraint.getReferencedTableName().replaceAll("[\"']", ""));
3536

3637
//In the Child table, create a new column having field name as Parent(Referenced) Table, with @ManyTOne annotation
@@ -72,33 +73,33 @@ private static void handleSingleForeignKey(final Table table, final ForeignKeyCo
7273
//Get the foreign key column from the table.
7374
List<Column> listOfForeignKeyColumns = listOfForeignKeys(table, foreignKeyConstraint);
7475
Column foreignKeyColumn = !listOfForeignKeyColumns.isEmpty() ? listOfForeignKeyColumns.get(0) : null;
75-
76-
if (foreignKeyColumn != null) {
77-
//Check if foreign key is also a primary key, by iterating through the primary key list
78-
Optional<Column> optionalColumnPrimaryForeign = allPrimaryKeyColumns.stream()
79-
.filter(column -> column.getColumnName() != null && column.getColumnName().equals(foreignKeyColumn.getColumnName())).findFirst();
80-
optionalColumnPrimaryForeign.ifPresentOrElse(column -> {
81-
//Case: Shared Primary key
82-
//If foreign key is a primary key, don't remove it from table. Set SharedPrimaryKey as true
83-
column.setSharedPrimaryKey(true);
84-
85-
//Remove existing column annotations and add again with updatable=false, insertable=false
86-
//This is necessary as the column is inserted/updated through foreign key
87-
column.getAnnotations().removeIf(s -> s.contains("@Column"));
88-
column.getAnnotations().add(ColumnAnnotation.builder()
89-
.columnName(column.getColumnName())
90-
.updatable(false)
91-
.insertable(false)
92-
.build().toString());
93-
94-
//Add a @MapsId annotation to the referenced table field
95-
parentTableField.getAnnotations().add(MapsIdAnnotation.builder().fieldName(column.getFieldName()).build().toString());
96-
}
97-
, () ->
98-
//If foreign key is not a primary key, then remove it from the table
99-
table.getColumns().remove(foreignKeyColumn)
100-
);
101-
}
76+
if(foreignKeyColumn == null) throw new UnsupportedOperationException(); //some issue in the SQL
77+
78+
//Case: Shared Single Primary Key
79+
//Check if foreign key is also a primary key, by iterating through the primary key list
80+
Optional<Column> optionalColumnPrimaryForeign = allPrimaryKeyColumns.stream()
81+
.filter(column -> column.getColumnName() != null && column.getColumnName().equals(foreignKeyColumn.getColumnName())).findFirst();
82+
optionalColumnPrimaryForeign.ifPresentOrElse(column -> {
83+
//Case: Shared Primary key
84+
//If foreign key is a primary key, don't remove it from table. Set SharedPrimaryKey as true
85+
column.setSharedPrimaryKey(true);
86+
//Add a @MapsId annotation to the referenced table field
87+
parentTableField.getAnnotations().add(MapsIdAnnotation.builder().fieldName(column.getFieldName()).build().toString());
88+
89+
//Remove existing column annotations and add again with updatable=false, insertable=false
90+
//This is necessary as the column is inserted/updated through foreign key
91+
column.getAnnotations().removeIf(s -> s.contains("@Column"));
92+
column.getAnnotations().add(ColumnAnnotation.builder()
93+
.columnName(column.getColumnName())
94+
.updatable(false)
95+
.insertable(false)
96+
.build().toString());
97+
98+
}
99+
, () ->
100+
//If foreign key is not a primary key, then remove it from the table
101+
table.getColumns().remove(foreignKeyColumn)
102+
);
102103

103104
//Add a @JoinColumn annotation for the referenced table field
104105
parentTableField.getAnnotations().add(JoinColumnAnnotation.builder()
@@ -118,6 +119,7 @@ private static void handleCompositeForeignKey(final Table table, final ForeignKe
118119
handleSharedCompositePrimaryKey(table, parentTableField, embeddableId, listOfForeignKeyColumns);
119120
} else {
120121
//Case1: There is no Composite primary key
122+
//TODO can part of Composite foreign key be a primary key. Is this applicable only to self referencing cases?
121123
//Case2: If composite foreign key is not inside the composite primary key, then remove it from the table
122124
listOfForeignKeyColumns.forEach(column -> table.getColumns().remove(column));
123125
}

src/main/java/io/github/ngbsn/generator/JPACodeGenerator.java renamed to src/main/java/io/github/ngbsn/generator/code/JPACodeGenerator.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
1-
package io.github.ngbsn.generator;
1+
package io.github.ngbsn.generator.code;
22

33
import freemarker.cache.StringTemplateLoader;
44
import freemarker.template.Configuration;
55
import freemarker.template.Template;
66
import freemarker.template.TemplateException;
77
import freemarker.template.TemplateExceptionHandler;
88
import io.github.ngbsn.exception.SQLParsingException;
9+
import io.github.ngbsn.generator.models.ModelGenerator;
910
import io.github.ngbsn.model.Table;
1011
import lombok.extern.slf4j.Slf4j;
1112
import org.slf4j.Logger;
@@ -102,6 +103,8 @@ private static void processTemplate(final List<Table> tables, final String packa
102103
imports.add("lombok.Getter");
103104
imports.add("lombok.Setter");
104105
imports.add("lombok.Builder");
106+
imports.add("lombok.NoArgsConstructor");
107+
imports.add("lombok.AllArgsConstructor");
105108
root.put("imports", imports);
106109

107110
/* Merge data-model with template */

src/main/java/io/github/ngbsn/generator/ModelGenerator.java renamed to src/main/java/io/github/ngbsn/generator/models/ModelGenerator.java

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
package io.github.ngbsn.generator;
1+
package io.github.ngbsn.generator.models;
22

33
import io.github.ngbsn.exception.SQLParsingException;
4+
import io.github.ngbsn.generator.associations.AssociationMappingsGenerator;
45
import io.github.ngbsn.model.*;
56
import io.github.ngbsn.model.annotations.entity.EntityAnnotation;
67
import io.github.ngbsn.model.annotations.entity.TableAnnotation;
@@ -59,7 +60,7 @@ public static Map<String, Table> getTablesMap() {
5960
* @param sqlScript The input DDL commands used for generating the models
6061
* @return List of Tables models
6162
*/
62-
static List<Table> parse(final String sqlScript) throws SQLParsingException {
63+
public static List<Table> parse(final String sqlScript) throws SQLParsingException {
6364
String extractedStatementWithoutDefaultConstraint = null;
6465
try {
6566
String[] extractedStatementsArray = sqlScript.split(";");
@@ -152,6 +153,32 @@ private static void processAlterTableStatements(final List<Statement> statements
152153
} else if (alterExpression.getIndex() != null && alterExpression.getIndex().getType().equals("PRIMARY KEY")) {
153154
//case: ALTER TABLE PRIMARY KEY
154155
extractPrimaryKeys(alterExpression.getIndex(), table);
156+
} else if (alterExpression.getOperation().name().equals("DROP")){
157+
table.getColumns().removeIf(column -> column.getColumnName().equals(alterExpression.getColumnName()));
158+
159+
} else if (alterExpression.getOperation().name().equals("ADD")){
160+
String cName = alterExpression.getColDataTypeList().get(0) != null ? alterExpression.getColDataTypeList().get(0).getColumnName() : null;
161+
String columnName = alterExpression.getColumnName() != null ? alterExpression.getColumnName() : cName;
162+
String type = alterExpression.getColDataTypeList().get(0) != null ?
163+
SQLTypeToJpaTypeMapping.getTypeMapping(alterExpression.getColDataTypeList().get(0).getColDataType().getDataType()) : null;
164+
Column column = new Column();
165+
column.setColumnName(columnName);
166+
column.setType(type);
167+
String fieldName = Util.convertSnakeCaseToCamelCase(column.getColumnName(), false);
168+
fieldName = SourceVersion.isKeyword(fieldName) ? fieldName + table.getClassName() : fieldName;
169+
column.setFieldName(fieldName);
170+
171+
//Check for NOT NULL
172+
if (alterExpression.getColDataTypeList().get(0) != null && alterExpression.getColDataTypeList().get(0).getColumnSpecs() != null) {
173+
List<String> fieldAnnotations = new ArrayList<>();
174+
175+
String constraints = String.join(" ", alterExpression.getColDataTypeList().get(0).getColumnSpecs());
176+
if (constraints.contains("NOT NULL")) {
177+
fieldAnnotations.add(NotNullAnnotation.builder().build().toString());
178+
}
179+
column.setAnnotations(fieldAnnotations);
180+
}
181+
table.getColumns().add(column);
155182
}
156183
});
157184
extractForeignKeys(foreignKeyIndexes, table);

src/main/java/io/github/ngbsn/maven/JPACodeGenMojo.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
package io.github.ngbsn.maven;
22

3-
import io.github.ngbsn.generator.JPACodeGenerator;
3+
import io.github.ngbsn.generator.code.JPACodeGenerator;
44
import lombok.SneakyThrows;
55
import lombok.extern.slf4j.Slf4j;
66
import org.apache.maven.plugin.AbstractMojo;

src/main/resources/templates/entity.ftl

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ import ${import};
66

77
// Generated source code
88

9+
@NoArgsConstructor
10+
@AllArgsConstructor
911
@Getter
1012
@Setter
1113
@Builder
@@ -28,6 +30,8 @@ public class ${table.className}{
2830

2931
<#if (table.numOfPrimaryKeyColumns > 1) >
3032
<#list table.embeddableClasses as embeddableClass>
33+
@NoArgsConstructor
34+
@AllArgsConstructor
3135
@Getter
3236
@Setter
3337
@Builder
@@ -44,6 +48,8 @@ public class ${table.className}{
4448
</#list>
4549

4650
<#if table.embeddedId??>
51+
@NoArgsConstructor
52+
@AllArgsConstructor
4753
@Getter
4854
@Setter
4955
@Builder
@@ -74,8 +80,8 @@ public class ${table.className}{
7480
<#list table.columns as column>
7581
<#if column.primaryKey == true>
7682
@Id
77-
<#if column.sharedPrimaryKey == false>
78-
@GeneratedValue(strategy = GenerationType.AUTO)
83+
<#if column.sharedPrimaryKey == false && (column.type == "Integer" || column.type == "Short" || column.type == "Long") >
84+
@GeneratedValue(strategy = GenerationType.IDENTITY)
7985
</#if>
8086
</#if>
8187
<#list column.annotations as annotation>

src/test/java/io/github/ngbsn/maven/CodeGenTest.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
package io.github.ngbsn.maven;
22

3-
import io.github.ngbsn.generator.ModelGenerator;
3+
import io.github.ngbsn.generator.models.ModelGenerator;
44
import lombok.extern.slf4j.Slf4j;
55
import org.apache.commons.io.FileUtils;
66
import org.junit.Assert;
@@ -13,7 +13,7 @@
1313
import java.nio.charset.StandardCharsets;
1414
import java.util.Objects;
1515

16-
import static io.github.ngbsn.generator.JPACodeGenerator.generateCode;
16+
import static io.github.ngbsn.generator.code.JPACodeGenerator.generateCode;
1717

1818

1919
//TODO write assertions

0 commit comments

Comments
 (0)