#3269 - @JoinColumns set ForeignKey is none in ddl , but is not work

This commit is contained in:
Rob Bygrave
2023-11-21 23:40:21 +13:00
parent c48e5428c5
commit f032aad22e
4 changed files with 64 additions and 28 deletions
@@ -1,5 +1,6 @@
package io.ebeaninternal.dbmigration.model;
import io.ebean.annotation.ConstraintMode;
import io.ebeaninternal.dbmigration.ddlgeneration.platform.DdlHelp;
import io.ebeaninternal.dbmigration.migration.AlterForeignKey;
import io.ebeaninternal.dbmigration.migration.ForeignKey;
@@ -22,6 +23,8 @@ public class MCompoundForeignKey {
private final List<String> columns = new ArrayList<>();
private final List<String> referenceColumns = new ArrayList<>();
private String indexName;
private ConstraintMode fkeyOnDelete;
private ConstraintMode fkeyOnUpdate;
public MCompoundForeignKey(String name, String referenceTable, String indexName) {
this.name = name;
@@ -47,9 +50,15 @@ public class MCompoundForeignKey {
fk.setColumnNames(toColumnNames(columns));
fk.setRefColumnNames(toColumnNames(referenceColumns));
fk.setRefTableName(referenceTable);
fk.setOnDelete(fkeyModeOf(fkeyOnDelete));
fk.setOnUpdate(fkeyModeOf(fkeyOnUpdate));
return fk;
}
private String fkeyModeOf(ConstraintMode mode) {
return (mode == null) ? null : mode.name();
}
/**
* Create and return an AlterForeignKey migration element.
*/
@@ -63,7 +72,7 @@ public class MCompoundForeignKey {
fk.setTableName(tableName);
return fk;
}
/**
* Create and return an AlterForeignKey migration element.
*/
@@ -117,7 +126,6 @@ public class MCompoundForeignKey {
* Return as an array of string column names.
*/
private String toColumnNames(List<String> columns) {
StringBuilder sb = new StringBuilder(40);
for (int i = 0; i < columns.size(); i++) {
if (i > 0) {
@@ -139,7 +147,7 @@ public class MCompoundForeignKey {
return true;
if (!(obj instanceof MCompoundForeignKey))
return false;
MCompoundForeignKey other = (MCompoundForeignKey) obj;
return Objects.equals(columns, other.columns)
&& Objects.equals(indexName, other.indexName)
@@ -148,4 +156,8 @@ public class MCompoundForeignKey {
&& Objects.equals(referenceTable, other.referenceTable);
}
public void setForeignKeyModes(ConstraintMode onDelete, ConstraintMode onUpdate) {
this.fkeyOnDelete = onDelete;
this.fkeyOnUpdate = onUpdate;
}
}
@@ -91,7 +91,6 @@ public class ModelBuildPropertyVisitor extends BaseTablePropertyVisitor {
@Override
public void visitEnd() {
// set the primary key name
table.setPkName(primaryKeyName());
@@ -169,6 +168,8 @@ public class ModelBuildPropertyVisitor extends BaseTablePropertyVisitor {
@Override
public void visitOneImported(BeanPropertyAssocOne<?> p) {
PropertyForeignKey foreignKey = p.foreignKey();
boolean addForeignKey = foreignKey == null || !foreignKey.isNoConstraint();
TableJoinColumn[] columns = p.tableJoin().columns();
if (columns.length == 0) {
@@ -178,17 +179,19 @@ public class ModelBuildPropertyVisitor extends BaseTablePropertyVisitor {
List<MColumn> modelColumns = new ArrayList<>(columns.length);
MCompoundForeignKey compoundKey = null;
if (columns.length > 1) {
if (addForeignKey && columns.length > 1) {
// compound foreign key
String refTable = p.targetDescriptor().baseTable();
String fkName = foreignKeyConstraintName(p.name());
String fkIndex = foreignKeyIndexName(p.name());
compoundKey = new MCompoundForeignKey(fkName, refTable, fkIndex);
if (foreignKey != null) {
compoundKey.setForeignKeyModes(foreignKey.getOnDelete(), foreignKey.getOnUpdate());
}
table.addForeignKey(compoundKey);
}
for (TableJoinColumn column : columns) {
String dbCol = column.getLocalDbColumn();
BeanProperty importedProperty = p.findMatchImport(dbCol);
if (importedProperty == null) {
@@ -200,26 +203,27 @@ public class ModelBuildPropertyVisitor extends BaseTablePropertyVisitor {
MColumn col = table.addColumn(dbCol, columnDefn, !p.isNullable());
col.setDbMigrationInfos(p.dbMigrationInfos());
col.setDefaultValue(p.dbColumnDefault());
if (columns.length == 1) {
if (p.hasForeignKeyConstraint() && !importedProperty.descriptor().suppressForeignKey()) {
// single references column (put it on the column)
String refTable = importedProperty.descriptor().baseTable();
if (refTable == null) {
// odd case where an EmbeddedId only has 1 property
refTable = p.targetDescriptor().baseTable();
}
col.setReferences(refTable + "." + refColumn);
col.setForeignKeyName(foreignKeyConstraintName(col.getName()));
if (p.hasForeignKeyIndex()) {
col.setForeignKeyIndex(foreignKeyIndexName(col.getName()));
}
PropertyForeignKey foreignKey = p.foreignKey();
if (foreignKey != null) {
col.setForeignKeyModes(foreignKey.getOnDelete(), foreignKey.getOnUpdate());
if (addForeignKey) {
if (columns.length > 1) {
compoundKey.addColumnPair(dbCol, refColumn);
} else {
if (p.hasForeignKeyConstraint() && !importedProperty.descriptor().suppressForeignKey()) {
// single references column (put it on the column)
String refTable = importedProperty.descriptor().baseTable();
if (refTable == null) {
// odd case where an EmbeddedId only has 1 property
refTable = p.targetDescriptor().baseTable();
}
col.setReferences(refTable + "." + refColumn);
col.setForeignKeyName(foreignKeyConstraintName(col.getName()));
if (p.hasForeignKeyIndex()) {
col.setForeignKeyIndex(foreignKeyIndexName(col.getName()));
}
if (foreignKey != null) {
col.setForeignKeyModes(foreignKey.getOnDelete(), foreignKey.getOnUpdate());
}
}
}
} else {
compoundKey.addColumnPair(dbCol, refColumn);
}
modelColumns.add(col);
}
@@ -1,8 +1,6 @@
package io.ebeaninternal.dbmigration.model.build;
import io.ebean.DatabaseBuilder;
import io.localtest.BaseTestCase;
import io.ebean.DB;
import io.ebean.DatabaseFactory;
import io.ebean.config.DatabaseConfig;
@@ -11,11 +9,13 @@ import io.ebean.platform.h2.H2Platform;
import io.ebean.platform.sqlserver.SqlServer17Platform;
import io.ebeaninternal.api.SpiEbeanServer;
import io.ebeaninternal.dbmigration.ddlgeneration.platform.DefaultConstraintMaxLength;
import io.ebeaninternal.dbmigration.migration.ForeignKey;
import io.ebeaninternal.dbmigration.model.MColumn;
import io.ebeaninternal.dbmigration.model.MCompoundForeignKey;
import io.ebeaninternal.dbmigration.model.MTable;
import io.ebeaninternal.dbmigration.model.ModelContainer;
import io.ebeaninternal.dbmigration.model.visitor.VisitAllUsing;
import io.localtest.BaseTestCase;
import org.junit.jupiter.api.Test;
import org.tests.model.basic.CKeyAssoc;
import org.tests.model.basic.CKeyDetail;
@@ -44,6 +44,7 @@ public class ModelBuildBeanVisitorTest extends BaseTestCase {
new VisitAllUsing(addTable, defaultServer).visitAllBeans();
assert_compound_pk(model);
assert_compound_fk(model);
assert_discriminatorColumn_explicit(model);
assert_discriminatorColumn_implied(model);
@@ -73,7 +74,7 @@ public class ModelBuildBeanVisitorTest extends BaseTestCase {
config.setDbOffline(true);
config.setDatabasePlatform(new SqlServer17Platform());
final SpiEbeanServer database = (SpiEbeanServer)DatabaseFactory.create(config);
final SpiEbeanServer database = (SpiEbeanServer) DatabaseFactory.create(config);
try {
ModelBuildContext ctx = new ModelBuildContext(model, config.getDatabasePlatform(), config.getConstraintNaming(), true);
@@ -105,6 +106,21 @@ public class ModelBuildBeanVisitorTest extends BaseTestCase {
assertThat(item.primaryKeyColumns()).hasSize(2);
}
private void assert_compound_fk(ModelContainer model) {
MTable item = model.getTable("item");
assertThat(item).isNotNull();
List<MCompoundForeignKey> compoundKeys = item.getCompoundKeys();
assertThat(compoundKeys).hasSize(1);
MCompoundForeignKey compoundForeignKey = compoundKeys.get(0);
ForeignKey foreignKey = compoundForeignKey.createForeignKey();
assertThat(foreignKey.getName()).isEqualTo("fk_item_etype");
assertThat(foreignKey.getColumnNames()).isEqualTo("customer,type");
assertThat(foreignKey.getRefTableName()).isEqualTo("\"type\"");
assertThat(foreignKey.getOnDelete()).isEqualTo("SET_NULL");
assertThat(foreignKey.getOnUpdate()).isEqualTo("SET_DEFAULT");
}
private void assert_discriminatorColumn_explicit(ModelContainer model) {
MTable configuration = model.getTable("configuration");
@@ -1,5 +1,7 @@
package org.tests.model.compositekeys;
import io.ebean.annotation.ConstraintMode;
import io.ebean.annotation.DbForeignKey;
import jakarta.persistence.AttributeOverride;
import jakarta.persistence.Column;
import jakarta.persistence.Embedded;
@@ -32,11 +34,13 @@ public class Item {
@Version
private Long version;
@DbForeignKey(onDelete = ConstraintMode.SET_NULL, onUpdate = ConstraintMode.SET_DEFAULT)
@ManyToOne
@JoinColumn(name = "customer", referencedColumnName = "customer", insertable = false, updatable = false)
@JoinColumn(name = "type", referencedColumnName = "type", insertable = false, updatable = false)
private Type eType;
@DbForeignKey(noConstraint = true)
@ManyToOne
@JoinColumn(name = "customer", referencedColumnName = "customer", insertable = false, updatable = false)
@JoinColumn(name = "region", referencedColumnName = "type", insertable = false, updatable = false)