mirror of
https://github.com/ebean-orm/ebean.git
synced 2026-10-23 16:47:18 +00:00
#323 - DDL Generation support for foreign key cascade options
This commit is contained in:
+17
-67
@@ -389,14 +389,7 @@ public class BaseTableDdl implements TableDdl {
|
||||
|
||||
protected void writeInlineForeignKey(DdlWrite write, Column column) throws IOException {
|
||||
|
||||
String references = column.getReferences();
|
||||
int pos = references.lastIndexOf('.');
|
||||
if (pos == -1) {
|
||||
throw new IllegalStateException("Expecting period '.' character for table.column split but not found in [" + references + "]");
|
||||
}
|
||||
String refTableName = references.substring(0, pos);
|
||||
String refColumnName = references.substring(pos + 1);
|
||||
String fkConstraint = platformDdl.tableInlineForeignKey(new String[]{column.getName()}, refTableName, new String[]{refColumnName});
|
||||
String fkConstraint = platformDdl.tableInlineForeignKey(new WriteForeignKey(null, column));
|
||||
write.apply().append(",").newLine().append(" ").append(fkConstraint);
|
||||
}
|
||||
|
||||
@@ -404,11 +397,7 @@ public class BaseTableDdl implements TableDdl {
|
||||
|
||||
List<ForeignKey> foreignKey = createTable.getForeignKey();
|
||||
for (ForeignKey key : foreignKey) {
|
||||
String refTableName = key.getRefTableName();
|
||||
String[] cols = toColumnNamesSplit(key.getColumnNames());
|
||||
String[] refColumns = toColumnNamesSplit(key.getRefColumnNames());
|
||||
|
||||
String fkConstraint = platformDdl.tableInlineForeignKey(cols, refTableName, refColumns);
|
||||
String fkConstraint = platformDdl.tableInlineForeignKey(new WriteForeignKey(null, key));
|
||||
write.apply().append(",").newLine().append(" ").append(fkConstraint);
|
||||
}
|
||||
}
|
||||
@@ -433,61 +422,42 @@ public class BaseTableDdl implements TableDdl {
|
||||
|
||||
List<ForeignKey> foreignKey = createTable.getForeignKey();
|
||||
for (ForeignKey key : foreignKey) {
|
||||
|
||||
String refTableName = key.getRefTableName();
|
||||
String fkName = key.getName();
|
||||
String[] cols = toColumnNamesSplit(key.getColumnNames());
|
||||
String[] refColumns = toColumnNamesSplit(key.getRefColumnNames());
|
||||
|
||||
writeForeignKey(write, fkName, tableName, cols, refTableName, refColumns, key.getIndexName());
|
||||
writeForeignKey(write, new WriteForeignKey(tableName, key));
|
||||
}
|
||||
}
|
||||
|
||||
protected void writeForeignKey(DdlWrite write, String tableName, Column column) throws IOException {
|
||||
|
||||
String fkName = column.getForeignKeyName();
|
||||
String references = column.getReferences();
|
||||
int pos = references.lastIndexOf('.');
|
||||
if (pos == -1) {
|
||||
throw new IllegalStateException("Expecting period '.' character for table.column split but not found in [" + references + "]");
|
||||
}
|
||||
String refTableName = references.substring(0, pos);
|
||||
String refColumnName = references.substring(pos + 1);
|
||||
|
||||
String[] cols = {column.getName()};
|
||||
String[] refCols = {refColumnName};
|
||||
|
||||
writeForeignKey(write, fkName, tableName, cols, refTableName, refCols, column.getForeignKeyIndex());
|
||||
writeForeignKey(write, new WriteForeignKey(tableName, column));
|
||||
}
|
||||
|
||||
protected void writeForeignKey(DdlWrite write, String fkName, String tableName, String[] columns, String refTable, String[] refColumns, String indexName) throws IOException {
|
||||
protected void writeForeignKey(DdlWrite write, WriteForeignKey request) throws IOException {
|
||||
|
||||
tableName = lowerTableName(tableName);
|
||||
String tableName = lowerTableName(request.table());
|
||||
DdlBuffer fkeyBuffer = write.applyForeignKeys();
|
||||
alterTableAddForeignKey(fkeyBuffer, fkName, tableName, columns, refTable, refColumns);
|
||||
alterTableAddForeignKey(fkeyBuffer, request);
|
||||
|
||||
if (indexName != null) {
|
||||
if (request.indexName() != null) {
|
||||
// no matching unique constraint so add the index
|
||||
fkeyBuffer.append(platformDdl.createIndex(indexName, tableName, columns)).endOfStatement();
|
||||
fkeyBuffer.append(platformDdl.createIndex(request.indexName(), tableName, request.cols())).endOfStatement();
|
||||
}
|
||||
|
||||
fkeyBuffer.end();
|
||||
|
||||
write.dropAllForeignKeys()
|
||||
.append(platformDdl.alterTableDropForeignKey(tableName, fkName)).endOfStatement();
|
||||
.append(platformDdl.alterTableDropForeignKey(tableName, request.fkName())).endOfStatement();
|
||||
|
||||
if (indexName != null) {
|
||||
if (request.indexName() != null) {
|
||||
write.dropAllForeignKeys()
|
||||
.append(platformDdl.dropIndex(indexName, tableName)).endOfStatement();
|
||||
.append(platformDdl.dropIndex(request.indexName(), tableName)).endOfStatement();
|
||||
}
|
||||
|
||||
write.dropAllForeignKeys().end();
|
||||
|
||||
}
|
||||
|
||||
protected void alterTableAddForeignKey(DdlBuffer buffer, String fkName, String tableName, String[] columns, String refTable, String[] refColumns) throws IOException {
|
||||
protected void alterTableAddForeignKey(DdlBuffer buffer, WriteForeignKey request) throws IOException {
|
||||
|
||||
String fkConstraint = platformDdl.alterTableAddForeignKey(tableName, fkName, columns, refTable, refColumns);
|
||||
String fkConstraint = platformDdl.alterTableAddForeignKey(request);
|
||||
if (fkConstraint != null && !fkConstraint.isEmpty()) {
|
||||
buffer.append(fkConstraint).endOfStatement();
|
||||
}
|
||||
@@ -554,7 +524,7 @@ public class BaseTableDdl implements TableDdl {
|
||||
for (UniqueConstraint uniqueConstraint : uniqueConstraints) {
|
||||
if (inlineUniqueWhenNull) {
|
||||
String uqName = uniqueConstraint.getName();
|
||||
String[] columns = toColumnNamesSplit(uniqueConstraint.getColumnNames());
|
||||
String[] columns = SplitColumns.split(uniqueConstraint.getColumnNames());
|
||||
apply.append(",").newLine();
|
||||
apply.append(" constraint ").append(uqName).append(" unique");
|
||||
appendColumns(columns, apply);
|
||||
@@ -625,13 +595,6 @@ public class BaseTableDdl implements TableDdl {
|
||||
return cols;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return as an array of string column names.
|
||||
*/
|
||||
protected String[] toColumnNamesSplit(String columns) {
|
||||
return columns.split(",");
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the table lower case.
|
||||
*/
|
||||
@@ -662,7 +625,7 @@ public class BaseTableDdl implements TableDdl {
|
||||
@Override
|
||||
public void generate(DdlWrite writer, CreateIndex createIndex) throws IOException {
|
||||
|
||||
String[] cols = toColumnNamesSplit(createIndex.getColumns());
|
||||
String[] cols = SplitColumns.split(createIndex.getColumns());
|
||||
writer.apply()
|
||||
.append(platformDdl.createIndex(createIndex.getIndexName(), createIndex.getTableName(), cols))
|
||||
.endOfStatement();
|
||||
@@ -931,22 +894,9 @@ public class BaseTableDdl implements TableDdl {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected void alterColumnAddForeignKey(DdlWrite writer, AlterColumn alterColumn) throws IOException {
|
||||
|
||||
String tableName = alterColumn.getTableName();
|
||||
String fkName = alterColumn.getForeignKeyName();
|
||||
String[] cols = {alterColumn.getColumnName()};
|
||||
String references = alterColumn.getReferences();
|
||||
int pos = references.lastIndexOf('.');
|
||||
if (pos == -1) {
|
||||
throw new IllegalStateException("Expecting period '.' character for table.column split but not found in [" + references + "]");
|
||||
}
|
||||
String refTableName = references.substring(0, pos);
|
||||
String refColumnName = references.substring(pos + 1);
|
||||
String[] refCols = {refColumnName};
|
||||
|
||||
alterTableAddForeignKey(writer.apply(), fkName, tableName, cols, refTableName, refCols);
|
||||
alterTableAddForeignKey(writer.apply(), new WriteForeignKey(alterColumn));
|
||||
}
|
||||
|
||||
protected void alterColumnDropForeignKey(DdlWrite writer, AlterColumn alter) throws IOException {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package io.ebeaninternal.dbmigration.ddlgeneration.platform;
|
||||
|
||||
import io.ebean.annotation.ConstraintMode;
|
||||
import io.ebean.config.dbplatform.DatabasePlatform;
|
||||
|
||||
/**
|
||||
@@ -14,7 +15,6 @@ public class Oracle10Ddl extends PlatformDdl {
|
||||
this.dropConstraintIfExists = "drop constraint";
|
||||
this.dropIndexIfExists = "drop index ";
|
||||
this.dropTableCascade = " cascade constraints purge";
|
||||
this.foreignKeyRestrict = "";
|
||||
this.alterColumn = "modify";
|
||||
this.columnSetNotnull = "not null";
|
||||
this.columnSetNull = "null";
|
||||
@@ -22,4 +22,20 @@ public class Oracle10Ddl extends PlatformDdl {
|
||||
this.identitySuffix = " generated always as identity";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void appendForeignKeyOnUpdate(StringBuilder buffer, ConstraintMode mode) {
|
||||
// do nothing, no on update clause for oracle
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void appendForeignKeyMode(StringBuilder buffer, String onMode, ConstraintMode mode) {
|
||||
switch (mode) {
|
||||
case SET_NULL:
|
||||
case CASCADE:
|
||||
super.appendForeignKeyMode(buffer, onMode, mode);
|
||||
default:
|
||||
// do nothing, defaults to RESTRICT effectively
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+48
-15
@@ -1,11 +1,13 @@
|
||||
package io.ebeaninternal.dbmigration.ddlgeneration.platform;
|
||||
|
||||
import io.ebean.annotation.ConstraintMode;
|
||||
import io.ebean.config.DbConstraintNaming;
|
||||
import io.ebean.config.ServerConfig;
|
||||
import io.ebean.config.dbplatform.DatabasePlatform;
|
||||
import io.ebean.config.dbplatform.DbDefaultValue;
|
||||
import io.ebean.config.dbplatform.DbIdentity;
|
||||
import io.ebean.config.dbplatform.IdType;
|
||||
import io.ebean.util.StringHelper;
|
||||
import io.ebeaninternal.dbmigration.ddlgeneration.BaseDdlHandler;
|
||||
import io.ebeaninternal.dbmigration.ddlgeneration.DdlBuffer;
|
||||
import io.ebeaninternal.dbmigration.ddlgeneration.DdlHandler;
|
||||
@@ -17,7 +19,6 @@ import io.ebeaninternal.dbmigration.migration.Column;
|
||||
import io.ebeaninternal.dbmigration.migration.DropHistoryTable;
|
||||
import io.ebeaninternal.dbmigration.migration.IdentityType;
|
||||
import io.ebeaninternal.dbmigration.model.MTable;
|
||||
import io.ebean.util.StringHelper;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@@ -62,7 +63,8 @@ public class PlatformDdl {
|
||||
*/
|
||||
protected String dropSequenceIfExists = "drop sequence if exists ";
|
||||
|
||||
protected String foreignKeyRestrict = "on delete restrict on update restrict";
|
||||
protected String foreignKeyOnDelete = "on delete";
|
||||
protected String foreignKeyOnUpdate = "on update";
|
||||
|
||||
protected String identitySuffix = " auto_increment";
|
||||
|
||||
@@ -351,37 +353,68 @@ public class PlatformDdl {
|
||||
/**
|
||||
* Return the foreign key constraint when used inline with create table.
|
||||
*/
|
||||
public String tableInlineForeignKey(String[] columns, String refTable, String[] refColumns) {
|
||||
public String tableInlineForeignKey(WriteForeignKey request) {
|
||||
|
||||
StringBuilder buffer = new StringBuilder(90);
|
||||
buffer.append("foreign key");
|
||||
appendColumns(columns, buffer);
|
||||
buffer.append(" references ").append(lowerTableName(refTable));
|
||||
appendColumns(refColumns, buffer);
|
||||
appendWithSpace(foreignKeyRestrict, buffer);
|
||||
appendColumns(request.cols(), buffer);
|
||||
buffer.append(" references ").append(lowerTableName(request.refTable()));
|
||||
appendColumns(request.refCols(), buffer);
|
||||
appendForeignKeySuffix(request, buffer);
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add foreign key.
|
||||
*/
|
||||
public String alterTableAddForeignKey(String tableName, String fkName, String[] columns, String refTable, String[] refColumns) {
|
||||
public String alterTableAddForeignKey(WriteForeignKey request) {
|
||||
|
||||
StringBuilder buffer = new StringBuilder(90);
|
||||
buffer
|
||||
.append("alter table ").append(tableName)
|
||||
.append(" add constraint ").append(fkName)
|
||||
.append("alter table ").append(lowerTableName(request.table()))
|
||||
.append(" add constraint ").append(request.fkName())
|
||||
.append(" foreign key");
|
||||
appendColumns(columns, buffer);
|
||||
appendColumns(request.cols(), buffer);
|
||||
buffer
|
||||
.append(" references ")
|
||||
.append(lowerTableName(refTable));
|
||||
appendColumns(refColumns, buffer);
|
||||
appendWithSpace(foreignKeyRestrict, buffer);
|
||||
|
||||
.append(lowerTableName(request.refTable()));
|
||||
appendColumns(request.refCols(), buffer);
|
||||
appendForeignKeySuffix(request, buffer);
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
protected void appendForeignKeySuffix(WriteForeignKey request, StringBuilder buffer) {
|
||||
appendForeignKeyOnDelete(buffer, withDefault(request.onDelete()));
|
||||
appendForeignKeyOnUpdate(buffer, withDefault(request.onDelete()));
|
||||
}
|
||||
|
||||
protected ConstraintMode withDefault(ConstraintMode mode) {
|
||||
return (mode == null || mode == ConstraintMode.GLOBAL_DEFAULT) ? ConstraintMode.RESTRICT : mode;
|
||||
}
|
||||
|
||||
protected void appendForeignKeyOnDelete(StringBuilder buffer, ConstraintMode mode) {
|
||||
appendForeignKeyMode(buffer, foreignKeyOnDelete, mode);
|
||||
}
|
||||
|
||||
protected void appendForeignKeyOnUpdate(StringBuilder buffer, ConstraintMode mode) {
|
||||
appendForeignKeyMode(buffer, foreignKeyOnUpdate, mode);
|
||||
}
|
||||
|
||||
protected void appendForeignKeyMode(StringBuilder buffer, String onMode, ConstraintMode mode) {
|
||||
buffer.append(" ").append(onMode).append(" ").append(translate(mode));
|
||||
}
|
||||
|
||||
protected String translate(ConstraintMode mode) {
|
||||
switch(mode) {
|
||||
case SET_NULL: return "set null";
|
||||
case SET_DEFAULT: return "set default";
|
||||
case RESTRICT: return "restrict";
|
||||
case CASCADE: return "cascade";
|
||||
default:
|
||||
throw new IllegalStateException("Unknown mode "+mode);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Drop a unique constraint from the table (Sometimes this is an index).
|
||||
*/
|
||||
|
||||
@@ -3,8 +3,6 @@ package io.ebeaninternal.dbmigration.ddlgeneration.platform;
|
||||
import io.ebean.config.dbplatform.DatabasePlatform;
|
||||
import io.ebeaninternal.dbmigration.ddlgeneration.DdlBuffer;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* DB2 platform specific DDL.
|
||||
*/
|
||||
@@ -17,17 +15,17 @@ public class SQLiteDdl extends PlatformDdl {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addTableComment(DdlBuffer apply, String tableName, String tableComment) throws IOException {
|
||||
public void addTableComment(DdlBuffer apply, String tableName, String tableComment) {
|
||||
// not supported
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addColumnComment(DdlBuffer apply, String table, String column, String comment) throws IOException {
|
||||
public void addColumnComment(DdlBuffer apply, String table, String column, String comment) {
|
||||
// not supported
|
||||
}
|
||||
|
||||
@Override
|
||||
public String alterTableAddForeignKey(String tableName, String fkName, String[] columns, String refTable, String[] refColumns) {
|
||||
public String alterTableAddForeignKey(WriteForeignKey request) {
|
||||
// not supported
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
package io.ebeaninternal.dbmigration.ddlgeneration.platform;
|
||||
|
||||
public class SplitColumns {
|
||||
|
||||
/**
|
||||
* Return as an array of string column names.
|
||||
*/
|
||||
public static String[] split(String columns) {
|
||||
return columns.split(",");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
package io.ebeaninternal.dbmigration.ddlgeneration.platform;
|
||||
|
||||
import io.ebean.annotation.ConstraintMode;
|
||||
import io.ebean.config.dbplatform.DatabasePlatform;
|
||||
import io.ebeaninternal.dbmigration.ddlgeneration.DdlBuffer;
|
||||
import io.ebeaninternal.dbmigration.migration.AlterColumn;
|
||||
@@ -14,7 +15,6 @@ public class SqlServerDdl extends PlatformDdl {
|
||||
public SqlServerDdl(DatabasePlatform platform) {
|
||||
super(platform);
|
||||
this.identitySuffix = " identity(1,1)";
|
||||
this.foreignKeyRestrict = "";
|
||||
this.alterTableIfExists = "";
|
||||
this.addColumn = "add";
|
||||
this.inlineUniqueWhenNullable = false;
|
||||
@@ -23,6 +23,13 @@ public class SqlServerDdl extends PlatformDdl {
|
||||
this.historyDdl = new SqlServerHistoryDdl();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void appendForeignKeyMode(StringBuilder buffer, String onMode, ConstraintMode mode) {
|
||||
if (mode != ConstraintMode.RESTRICT) {
|
||||
super.appendForeignKeyMode(buffer, onMode, mode);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String dropTable(String tableName) {
|
||||
StringBuilder buffer = new StringBuilder();
|
||||
|
||||
+100
@@ -0,0 +1,100 @@
|
||||
package io.ebeaninternal.dbmigration.ddlgeneration.platform;
|
||||
|
||||
import io.ebean.annotation.ConstraintMode;
|
||||
import io.ebeaninternal.dbmigration.migration.AlterColumn;
|
||||
import io.ebeaninternal.dbmigration.migration.Column;
|
||||
import io.ebeaninternal.dbmigration.migration.ForeignKey;
|
||||
|
||||
class WriteForeignKey {
|
||||
|
||||
private final String fkName;
|
||||
private final String tableName;
|
||||
private final String[] cols;
|
||||
private String refTableName;
|
||||
private String[] refCols;
|
||||
private final String indexName;
|
||||
private final ConstraintMode onDelete;
|
||||
private final ConstraintMode onUpdate;
|
||||
|
||||
WriteForeignKey(AlterColumn alterColumn) {
|
||||
this.tableName = alterColumn.getTableName();
|
||||
this.indexName = alterColumn.getForeignKeyIndex();
|
||||
this.fkName = alterColumn.getForeignKeyName();
|
||||
this.cols = new String[]{alterColumn.getColumnName()};
|
||||
setReferences(alterColumn.getReferences());
|
||||
this.onDelete = modeOf(alterColumn.getForeignKeyOnDelete());
|
||||
this.onUpdate = modeOf(alterColumn.getForeignKeyOnUpdate());
|
||||
}
|
||||
|
||||
WriteForeignKey(String tableName, ForeignKey key) {
|
||||
this.tableName = tableName;
|
||||
this.indexName = key.getIndexName();
|
||||
this.fkName = key.getName();
|
||||
this.cols = toCols(key.getColumnNames());
|
||||
this.refTableName = key.getRefTableName();
|
||||
this.refCols = toCols(key.getRefColumnNames());
|
||||
this.onDelete = modeOf(key.getOnDelete());
|
||||
this.onUpdate = modeOf(key.getOnUpdate());
|
||||
}
|
||||
|
||||
WriteForeignKey(String tableName, Column column) {
|
||||
this.tableName = tableName;
|
||||
this.indexName = column.getForeignKeyIndex();
|
||||
this.fkName = column.getForeignKeyName();
|
||||
this.cols = new String[]{column.getName()};
|
||||
setReferences(column.getReferences());
|
||||
this.onDelete = modeOf(column.getForeignKeyOnDelete());
|
||||
this.onUpdate = modeOf(column.getForeignKeyOnUpdate());
|
||||
}
|
||||
|
||||
private void setReferences(String references) {
|
||||
int pos = references.lastIndexOf('.');
|
||||
if (pos == -1) {
|
||||
throw new IllegalStateException("Expecting period '.' character for table.column split but not found in [" + references + "]");
|
||||
}
|
||||
this.refTableName = references.substring(0, pos);
|
||||
String refColumnName = references.substring(pos + 1);
|
||||
this.refCols = new String[]{refColumnName};
|
||||
}
|
||||
|
||||
private String[] toCols(String columns) {
|
||||
return SplitColumns.split(columns);
|
||||
}
|
||||
|
||||
private ConstraintMode modeOf(String value) {
|
||||
return (value == null) ? null : ConstraintMode.valueOf(value);
|
||||
}
|
||||
|
||||
public String table() {
|
||||
return tableName;
|
||||
}
|
||||
|
||||
public String[] cols() {
|
||||
return cols;
|
||||
}
|
||||
|
||||
public String indexName() {
|
||||
return indexName;
|
||||
}
|
||||
|
||||
public String fkName() {
|
||||
return fkName;
|
||||
}
|
||||
|
||||
public String refTable() {
|
||||
return refTableName;
|
||||
}
|
||||
|
||||
public String[] refCols() {
|
||||
return refCols;
|
||||
}
|
||||
|
||||
public ConstraintMode onDelete() {
|
||||
return onDelete;
|
||||
}
|
||||
|
||||
public ConstraintMode onUpdate() {
|
||||
return onUpdate;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,14 +1,13 @@
|
||||
package io.ebeaninternal.dbmigration.migration;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.xml.bind.annotation.XmlAccessType;
|
||||
import javax.xml.bind.annotation.XmlAccessorType;
|
||||
import javax.xml.bind.annotation.XmlAttribute;
|
||||
import javax.xml.bind.annotation.XmlElement;
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
import javax.xml.bind.annotation.XmlType;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
/**
|
||||
@@ -40,6 +39,8 @@ import javax.xml.bind.annotation.XmlType;
|
||||
* <attribute name="references" type="{http://www.w3.org/2001/XMLSchema}string" />
|
||||
* <attribute name="foreignKeyName" type="{http://www.w3.org/2001/XMLSchema}string" />
|
||||
* <attribute name="foreignKeyIndex" type="{http://www.w3.org/2001/XMLSchema}string" />
|
||||
* <attribute name="foreignKeyOnDelete" type="{http://www.w3.org/2001/XMLSchema}string" />
|
||||
* <attribute name="foreignKeyOnUpdate" type="{http://www.w3.org/2001/XMLSchema}string" />
|
||||
* <attribute name="dropForeignKey" type="{http://www.w3.org/2001/XMLSchema}string" />
|
||||
* <attribute name="dropForeignKeyIndex" type="{http://www.w3.org/2001/XMLSchema}string" />
|
||||
* </restriction>
|
||||
@@ -99,6 +100,10 @@ public class AlterColumn {
|
||||
protected String foreignKeyName;
|
||||
@XmlAttribute(name = "foreignKeyIndex")
|
||||
protected String foreignKeyIndex;
|
||||
@XmlAttribute(name = "foreignKeyOnDelete")
|
||||
protected String foreignKeyOnDelete;
|
||||
@XmlAttribute(name = "foreignKeyOnUpdate")
|
||||
protected String foreignKeyOnUpdate;
|
||||
@XmlAttribute(name = "dropForeignKey")
|
||||
protected String dropForeignKey;
|
||||
@XmlAttribute(name = "dropForeignKeyIndex")
|
||||
@@ -504,6 +509,46 @@ public class AlterColumn {
|
||||
this.foreignKeyIndex = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value of the foreignKeyOnDelete property.
|
||||
*
|
||||
* @return possible object is
|
||||
* {@link String }
|
||||
*/
|
||||
public String getForeignKeyOnDelete() {
|
||||
return foreignKeyOnDelete;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value of the foreignKeyOnDelete property.
|
||||
*
|
||||
* @param value allowed object is
|
||||
* {@link String }
|
||||
*/
|
||||
public void setForeignKeyOnDelete(String value) {
|
||||
this.foreignKeyOnDelete = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value of the foreignKeyOnUpdate property.
|
||||
*
|
||||
* @return possible object is
|
||||
* {@link String }
|
||||
*/
|
||||
public String getForeignKeyOnUpdate() {
|
||||
return foreignKeyOnUpdate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value of the foreignKeyOnUpdate property.
|
||||
*
|
||||
* @param value allowed object is
|
||||
* {@link String }
|
||||
*/
|
||||
public void setForeignKeyOnUpdate(String value) {
|
||||
this.foreignKeyOnUpdate = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value of the dropForeignKey property.
|
||||
*
|
||||
|
||||
@@ -1,14 +1,13 @@
|
||||
package io.ebeaninternal.dbmigration.migration;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.xml.bind.annotation.XmlAccessType;
|
||||
import javax.xml.bind.annotation.XmlAccessorType;
|
||||
import javax.xml.bind.annotation.XmlAttribute;
|
||||
import javax.xml.bind.annotation.XmlElement;
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
import javax.xml.bind.annotation.XmlType;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
/**
|
||||
@@ -34,6 +33,8 @@ import javax.xml.bind.annotation.XmlType;
|
||||
* <attribute name="references" type="{http://www.w3.org/2001/XMLSchema}string" />
|
||||
* <attribute name="foreignKeyName" type="{http://www.w3.org/2001/XMLSchema}string" />
|
||||
* <attribute name="foreignKeyIndex" type="{http://www.w3.org/2001/XMLSchema}string" />
|
||||
* <attribute name="foreignKeyOnDelete" type="{http://www.w3.org/2001/XMLSchema}string" />
|
||||
* <attribute name="foreignKeyOnUpdate" type="{http://www.w3.org/2001/XMLSchema}string" />
|
||||
* <attribute name="comment" type="{http://www.w3.org/2001/XMLSchema}string" />
|
||||
* </restriction>
|
||||
* </complexContent>
|
||||
@@ -80,6 +81,10 @@ public class Column {
|
||||
protected String foreignKeyName;
|
||||
@XmlAttribute(name = "foreignKeyIndex")
|
||||
protected String foreignKeyIndex;
|
||||
@XmlAttribute(name = "foreignKeyOnDelete")
|
||||
protected String foreignKeyOnDelete;
|
||||
@XmlAttribute(name = "foreignKeyOnUpdate")
|
||||
protected String foreignKeyOnUpdate;
|
||||
@XmlAttribute(name = "comment")
|
||||
protected String comment;
|
||||
|
||||
@@ -378,6 +383,46 @@ public class Column {
|
||||
this.foreignKeyIndex = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value of the foreignOnDelete property.
|
||||
*
|
||||
* @return possible object is
|
||||
* {@link String }
|
||||
*/
|
||||
public String getForeignKeyOnDelete() {
|
||||
return foreignKeyOnDelete;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value of the foreignKeyOnDelete property.
|
||||
*
|
||||
* @param value allowed object is
|
||||
* {@link String }
|
||||
*/
|
||||
public void setForeignKeyOnDelete(String value) {
|
||||
this.foreignKeyOnDelete = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value of the foreignOnUpdate property.
|
||||
*
|
||||
* @return possible object is
|
||||
* {@link String }
|
||||
*/
|
||||
public String getForeignKeyOnUpdate() {
|
||||
return foreignKeyOnUpdate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value of the foreignKeyOnUpdate property.
|
||||
*
|
||||
* @param value allowed object is
|
||||
* {@link String }
|
||||
*/
|
||||
public void setForeignKeyOnUpdate(String value) {
|
||||
this.foreignKeyOnUpdate = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value of the comment property.
|
||||
*
|
||||
|
||||
@@ -21,6 +21,8 @@ import javax.xml.bind.annotation.XmlType;
|
||||
* <attribute name="refColumnNames" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
|
||||
* <attribute name="refTableName" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
|
||||
* <attribute name="indexName" type="{http://www.w3.org/2001/XMLSchema}string" />
|
||||
* <attribute name="onDelete" type="{http://www.w3.org/2001/XMLSchema}string" />
|
||||
* <attribute name="onUpdate" type="{http://www.w3.org/2001/XMLSchema}string" />
|
||||
* </restriction>
|
||||
* </complexContent>
|
||||
* </complexType>
|
||||
@@ -41,7 +43,10 @@ public class ForeignKey {
|
||||
protected String refTableName;
|
||||
@XmlAttribute(name = "indexName")
|
||||
protected String indexName;
|
||||
|
||||
@XmlAttribute(name = "onDelete")
|
||||
protected String onDelete;
|
||||
@XmlAttribute(name = "onUpdate")
|
||||
protected String onUpdate;
|
||||
/**
|
||||
* Gets the value of the name property.
|
||||
*
|
||||
@@ -142,4 +147,44 @@ public class ForeignKey {
|
||||
this.indexName = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value of the onDelete property.
|
||||
*
|
||||
* @return possible object is
|
||||
* {@link String }
|
||||
*/
|
||||
public String getOnDelete() {
|
||||
return onDelete;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value of the onDelete property.
|
||||
*
|
||||
* @param value allowed object is
|
||||
* {@link String }
|
||||
*/
|
||||
public void setOnDelete(String value) {
|
||||
this.onDelete = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value of the onUpdate property.
|
||||
*
|
||||
* @return possible object is
|
||||
* {@link String }
|
||||
*/
|
||||
public String getOnUpdate() {
|
||||
return onUpdate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value of the onUpdate property.
|
||||
*
|
||||
* @param value allowed object is
|
||||
* {@link String }
|
||||
*/
|
||||
public void setOnUpdate(String value) {
|
||||
this.onUpdate = value;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
package io.ebeaninternal.dbmigration.model;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import io.ebean.annotation.ConstraintMode;
|
||||
import io.ebeaninternal.dbmigration.ddlgeneration.platform.DdlHelp;
|
||||
import io.ebeaninternal.dbmigration.migration.AlterColumn;
|
||||
import io.ebeaninternal.dbmigration.migration.Column;
|
||||
import io.ebeaninternal.dbmigration.migration.DdlScript;
|
||||
import io.ebeaninternal.server.deploy.DbMigrationInfo;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A column in the logical model.
|
||||
*/
|
||||
@@ -21,6 +22,8 @@ public class MColumn {
|
||||
private String references;
|
||||
private String foreignKeyName;
|
||||
private String foreignKeyIndex;
|
||||
private ConstraintMode fkeyOnDelete;
|
||||
private ConstraintMode fkeyOnUpdate;
|
||||
private String comment;
|
||||
|
||||
private boolean historyExclude;
|
||||
@@ -55,6 +58,8 @@ public class MColumn {
|
||||
this.references = column.getReferences();
|
||||
this.foreignKeyName = column.getForeignKeyName();
|
||||
this.foreignKeyIndex = column.getForeignKeyIndex();
|
||||
this.fkeyOnDelete = fkeyMode(column.getForeignKeyOnDelete());
|
||||
this.fkeyOnUpdate = fkeyMode(column.getForeignKeyOnUpdate());
|
||||
this.notnull = Boolean.TRUE.equals(column.isNotnull());
|
||||
this.primaryKey = Boolean.TRUE.equals(column.isPrimaryKey());
|
||||
this.identity = Boolean.TRUE.equals(column.isIdentity());
|
||||
@@ -63,6 +68,10 @@ public class MColumn {
|
||||
this.historyExclude = Boolean.TRUE.equals(column.isHistoryExclude());
|
||||
}
|
||||
|
||||
private ConstraintMode fkeyMode(String mode) {
|
||||
return (mode == null) ? null : ConstraintMode.valueOf(mode);
|
||||
}
|
||||
|
||||
public MColumn(String name, String type) {
|
||||
this.name = name;
|
||||
this.type = type;
|
||||
@@ -89,6 +98,8 @@ public class MColumn {
|
||||
copy.comment = comment;
|
||||
copy.foreignKeyName = foreignKeyName;
|
||||
copy.foreignKeyIndex = foreignKeyIndex;
|
||||
copy.fkeyOnUpdate = fkeyOnUpdate;
|
||||
copy.fkeyOnDelete = fkeyOnDelete;
|
||||
copy.historyExclude = historyExclude;
|
||||
copy.notnull = notnull;
|
||||
copy.primaryKey = primaryKey;
|
||||
@@ -154,6 +165,11 @@ public class MColumn {
|
||||
this.foreignKeyIndex = foreignKeyIndex;
|
||||
}
|
||||
|
||||
public void setForeignKeyModes(ConstraintMode onDelete, ConstraintMode onUpdate) {
|
||||
this.fkeyOnDelete = onDelete;
|
||||
this.fkeyOnUpdate = onUpdate;
|
||||
}
|
||||
|
||||
public String getDefaultValue() {
|
||||
return defaultValue;
|
||||
}
|
||||
@@ -196,7 +212,7 @@ public class MColumn {
|
||||
|
||||
/**
|
||||
* Set unique specifically for OneToOne mapping.
|
||||
* We need special DDL for this case for MsSqlServer.
|
||||
* We need special DDL for this case for SqlServer.
|
||||
*/
|
||||
public void setUniqueOneToOne(String uniqueOneToOne) {
|
||||
this.uniqueOneToOne = uniqueOneToOne;
|
||||
@@ -260,6 +276,8 @@ public class MColumn {
|
||||
c.setReferences(references);
|
||||
c.setForeignKeyName(foreignKeyName);
|
||||
c.setForeignKeyIndex(foreignKeyIndex);
|
||||
c.setForeignKeyOnDelete(fkeyModeOf(fkeyOnDelete));
|
||||
c.setForeignKeyOnUpdate(fkeyModeOf(fkeyOnUpdate));
|
||||
c.setDefaultValue(defaultValue);
|
||||
c.setComment(comment);
|
||||
c.setUnique(unique);
|
||||
@@ -286,6 +304,10 @@ public class MColumn {
|
||||
return c;
|
||||
}
|
||||
|
||||
private String fkeyModeOf(ConstraintMode mode) {
|
||||
return (mode == null) ? null : mode.name();
|
||||
}
|
||||
|
||||
protected static boolean different(String val1, String val2) {
|
||||
return (val1 == null) ? val2 != null : !val1.equals(val2);
|
||||
}
|
||||
|
||||
+18
-8
@@ -11,6 +11,7 @@ import io.ebeaninternal.server.deploy.BeanPropertyAssocMany;
|
||||
import io.ebeaninternal.server.deploy.BeanPropertyAssocOne;
|
||||
import io.ebeaninternal.server.deploy.IndexDefinition;
|
||||
import io.ebeaninternal.server.deploy.InheritInfo;
|
||||
import io.ebeaninternal.server.deploy.PropertyForeignKey;
|
||||
import io.ebeaninternal.server.deploy.TableJoin;
|
||||
import io.ebeaninternal.server.deploy.TableJoinColumn;
|
||||
import io.ebeaninternal.server.deploy.id.ImportedId;
|
||||
@@ -156,6 +157,8 @@ public class ModelBuildPropertyVisitor extends BaseTablePropertyVisitor {
|
||||
|
||||
List<MColumn> modelColumns = new ArrayList<>(columns.length);
|
||||
|
||||
PropertyForeignKey foreignKey = p.getForeignKey();
|
||||
|
||||
MCompoundForeignKey compoundKey = null;
|
||||
if (columns.length > 1) {
|
||||
// compound foreign key
|
||||
@@ -180,15 +183,22 @@ public class ModelBuildPropertyVisitor extends BaseTablePropertyVisitor {
|
||||
col.setDbMigrationInfos(p.getDbMigrationInfos());
|
||||
col.setDefaultValue(p.getDbColumnDefault());
|
||||
if (columns.length == 1) {
|
||||
// single references column (put it on the column)
|
||||
String refTable = importedProperty.getBeanDescriptor().getBaseTable();
|
||||
if (refTable == null) {
|
||||
// odd case where an EmbeddedId only has 1 property
|
||||
refTable = p.getTargetDescriptor().getBaseTable();
|
||||
if (p.hasForeignKey()) {
|
||||
// single references column (put it on the column)
|
||||
String refTable = importedProperty.getBeanDescriptor().getBaseTable();
|
||||
if (refTable == null) {
|
||||
// odd case where an EmbeddedId only has 1 property
|
||||
refTable = p.getTargetDescriptor().getBaseTable();
|
||||
}
|
||||
col.setReferences(refTable + "." + refColumn);
|
||||
col.setForeignKeyName(determineForeignKeyConstraintName(col.getName()));
|
||||
if (p.hasForeignKeyIndex()) {
|
||||
col.setForeignKeyIndex(determineForeignKeyIndexName(col.getName()));
|
||||
}
|
||||
if (foreignKey != null) {
|
||||
col.setForeignKeyModes(foreignKey.getOnDelete(), foreignKey.getOnUpdate());
|
||||
}
|
||||
}
|
||||
col.setReferences(refTable + "." + refColumn);
|
||||
col.setForeignKeyName(determineForeignKeyConstraintName(col.getName()));
|
||||
col.setForeignKeyIndex(determineForeignKeyIndexName(col.getName()));
|
||||
} else {
|
||||
compoundKey.addColumnPair(dbCol, refColumn);
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package io.ebeaninternal.server.deploy;
|
||||
import io.ebean.BackgroundExecutor;
|
||||
import io.ebean.Model;
|
||||
import io.ebean.RawSqlBuilder;
|
||||
import io.ebean.annotation.ConstraintMode;
|
||||
import io.ebean.bean.BeanCollection;
|
||||
import io.ebean.bean.EntityBean;
|
||||
import io.ebean.config.EncryptKey;
|
||||
@@ -1156,7 +1157,6 @@ public class BeanDescriptorManager implements BeanDescriptorMap {
|
||||
// get the mappedBy property
|
||||
DeployBeanProperty mappedProp = targetDesc.getBeanProperty(mappedBy);
|
||||
if (mappedProp == null) {
|
||||
|
||||
String m = "Error on " + prop.getFullBeanName();
|
||||
m += " Can not find mappedBy property [" + mappedBy + "] ";
|
||||
m += "in [" + targetDesc + "]";
|
||||
@@ -1179,6 +1179,19 @@ public class BeanDescriptorManager implements BeanDescriptorMap {
|
||||
otherTableJoin.copyTo(tableJoin, true, tableJoin.getTable());
|
||||
}
|
||||
|
||||
PropertyForeignKey foreignKey = mappedAssocOne.getForeignKey();
|
||||
if (foreignKey != null) {
|
||||
ConstraintMode onDelete = foreignKey.getOnDelete();
|
||||
switch (onDelete) {
|
||||
case SET_DEFAULT:
|
||||
case SET_NULL:
|
||||
case CASCADE: {
|
||||
// turn off cascade delete when we are using the foreign
|
||||
// key constraint to cascade the delete or set null
|
||||
prop.getCascadeInfo().setDelete(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -41,6 +41,8 @@ public class BeanPropertyAssocOne<T> extends BeanPropertyAssoc<T> {
|
||||
|
||||
private final boolean primaryKeyExport;
|
||||
|
||||
private final PropertyForeignKey foreignKey;
|
||||
|
||||
private AssocOneHelp localHelp;
|
||||
|
||||
protected final BeanProperty[] embeddedProps;
|
||||
@@ -69,6 +71,7 @@ public class BeanPropertyAssocOne<T> extends BeanPropertyAssoc<T> {
|
||||
|
||||
super(descriptor, deploy);
|
||||
|
||||
foreignKey = deploy.getForeignKey();
|
||||
primaryKeyExport = deploy.isPrimaryKeyExport();
|
||||
importedPrimaryKey = deploy.isImportedPrimaryKey();
|
||||
oneToOne = deploy.isOneToOne();
|
||||
@@ -309,6 +312,18 @@ public class BeanPropertyAssocOne<T> extends BeanPropertyAssoc<T> {
|
||||
}
|
||||
}
|
||||
|
||||
public PropertyForeignKey getForeignKey() {
|
||||
return foreignKey;
|
||||
}
|
||||
|
||||
public boolean hasForeignKey() {
|
||||
return foreignKey == null || !foreignKey.isNoConstraint();
|
||||
}
|
||||
|
||||
public boolean hasForeignKeyIndex() {
|
||||
return foreignKey == null || !foreignKey.isNoIndex();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if this a OneToOne property. Otherwise assumed ManyToOne.
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
package io.ebeaninternal.server.deploy;
|
||||
|
||||
import io.ebean.annotation.ConstraintMode;
|
||||
import io.ebean.annotation.DbForeignKey;
|
||||
|
||||
public class PropertyForeignKey {
|
||||
|
||||
private final boolean noIndex;
|
||||
private final boolean noConstraint;
|
||||
private final ConstraintMode onDelete;
|
||||
private final ConstraintMode onUpdate;
|
||||
|
||||
public PropertyForeignKey(DbForeignKey dbForeignKey) {
|
||||
this.noIndex = dbForeignKey.noIndex();
|
||||
this.noConstraint = dbForeignKey.noConstraint();
|
||||
this.onDelete = dbForeignKey.onDelete();
|
||||
this.onUpdate = dbForeignKey.onUpdate();
|
||||
}
|
||||
|
||||
public boolean isNoIndex() {
|
||||
return noIndex;
|
||||
}
|
||||
|
||||
public boolean isNoConstraint() {
|
||||
return noConstraint;
|
||||
}
|
||||
|
||||
public ConstraintMode getOnDelete() {
|
||||
return onDelete;
|
||||
}
|
||||
|
||||
public ConstraintMode getOnUpdate() {
|
||||
return onUpdate;
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,7 @@
|
||||
package io.ebeaninternal.server.deploy.meta;
|
||||
|
||||
import io.ebeaninternal.server.deploy.PropertyForeignKey;
|
||||
|
||||
import javax.persistence.CascadeType;
|
||||
|
||||
/**
|
||||
@@ -21,6 +23,8 @@ public class DeployBeanPropertyAssocOne<T> extends DeployBeanPropertyAssoc<T> {
|
||||
|
||||
private String columnPrefix;
|
||||
|
||||
private PropertyForeignKey foreignKey;
|
||||
|
||||
/**
|
||||
* Create the property.
|
||||
*/
|
||||
@@ -148,4 +152,12 @@ public class DeployBeanPropertyAssocOne<T> extends DeployBeanPropertyAssoc<T> {
|
||||
cascadeInfo.setType(CascadeType.ALL);
|
||||
}
|
||||
}
|
||||
|
||||
public void setForeignKey(PropertyForeignKey foreignKey) {
|
||||
this.foreignKey = foreignKey;
|
||||
}
|
||||
|
||||
public PropertyForeignKey getForeignKey() {
|
||||
return foreignKey;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
package io.ebeaninternal.server.deploy.parse;
|
||||
|
||||
import io.ebean.annotation.DbForeignKey;
|
||||
import io.ebean.annotation.FetchPreference;
|
||||
import io.ebean.annotation.Where;
|
||||
import io.ebean.config.NamingConvention;
|
||||
import io.ebeaninternal.server.deploy.BeanDescriptorManager;
|
||||
import io.ebeaninternal.server.deploy.BeanTable;
|
||||
import io.ebeaninternal.server.deploy.PropertyForeignKey;
|
||||
import io.ebeaninternal.server.deploy.meta.DeployBeanProperty;
|
||||
import io.ebeaninternal.server.deploy.meta.DeployBeanPropertyAssoc;
|
||||
import io.ebeaninternal.server.deploy.meta.DeployBeanPropertyAssocOne;
|
||||
@@ -89,6 +91,11 @@ public class AnnotationAssocOnes extends AnnotationParser {
|
||||
prop.setNullable(false);
|
||||
}
|
||||
|
||||
DbForeignKey dbForeignKey = get(prop, DbForeignKey.class);
|
||||
if (dbForeignKey != null){
|
||||
prop.setForeignKey(new PropertyForeignKey(dbForeignKey));
|
||||
}
|
||||
|
||||
Where where = get(prop, Where.class);
|
||||
if (where != null) {
|
||||
// not expecting this to be used on assoc one properties
|
||||
|
||||
@@ -136,6 +136,8 @@
|
||||
<xsd:attribute name="refColumnNames" type="xsd:string" use="required"/>
|
||||
<xsd:attribute name="refTableName" type="xsd:string" use="required"/>
|
||||
<xsd:attribute name="indexName" type="xsd:string"/>
|
||||
<xsd:attribute name="onDelete" type="xsd:string"/>
|
||||
<xsd:attribute name="onUpdate" type="xsd:string"/>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
|
||||
@@ -221,6 +223,8 @@
|
||||
<xsd:attribute name="references" type="xsd:string"/>
|
||||
<xsd:attribute name="foreignKeyName" type="xsd:string"/>
|
||||
<xsd:attribute name="foreignKeyIndex" type="xsd:string"/>
|
||||
<xsd:attribute name="foreignOnDelete" type="xsd:string"/>
|
||||
<xsd:attribute name="foreignOnUpdate" type="xsd:string"/>
|
||||
<xsd:attribute name="dropForeignKey" type="xsd:string"/>
|
||||
<xsd:attribute name="dropForeignKeyIndex" type="xsd:string"/>
|
||||
</xsd:complexType>
|
||||
@@ -271,6 +275,8 @@
|
||||
<xsd:attribute name="references" type="xsd:string"/>
|
||||
<xsd:attribute name="foreignKeyName" type="xsd:string"/>
|
||||
<xsd:attribute name="foreignKeyIndex" type="xsd:string"/>
|
||||
<xsd:attribute name="foreignKeyOnDelete" type="xsd:string"/>
|
||||
<xsd:attribute name="foreignKeyOnUpdate" type="xsd:string"/>
|
||||
<xsd:attribute name="comment" type="xsd:string"/>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
|
||||
+54
@@ -0,0 +1,54 @@
|
||||
package io.ebeaninternal.dbmigration.ddlgeneration.platform;
|
||||
|
||||
import io.ebean.annotation.ConstraintMode;
|
||||
import io.ebean.config.dbplatform.oracle.OraclePlatform;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
public class Oracle10DdlTest {
|
||||
|
||||
Oracle10Ddl create() {
|
||||
return new Oracle10Ddl(new OraclePlatform());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void appendForeignKeyOnDelete_expectEmtpy_when_nullRestrictSetDefault() {
|
||||
|
||||
Oracle10Ddl oracle = create();
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
oracle.appendForeignKeyOnDelete(sb, oracle.withDefault(null));
|
||||
assertThat(sb.toString()).isEqualTo("");
|
||||
|
||||
sb = new StringBuilder();
|
||||
oracle.appendForeignKeyOnDelete(sb, ConstraintMode.RESTRICT);
|
||||
assertThat(sb.toString()).isEqualTo("");
|
||||
|
||||
|
||||
sb = new StringBuilder();
|
||||
oracle.appendForeignKeyOnDelete(sb, ConstraintMode.SET_DEFAULT);
|
||||
assertThat(sb.toString()).isEqualTo("");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void appendForeignKeyOnDelete_setNull() {
|
||||
|
||||
Oracle10Ddl oracle = create();
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
oracle.appendForeignKeyOnDelete(sb, ConstraintMode.SET_NULL);
|
||||
assertThat(sb.toString()).isEqualTo(" on delete set null");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void appendForeignKeyOnDelete_cascade() {
|
||||
|
||||
Oracle10Ddl oracle = create();
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
oracle.appendForeignKeyOnDelete(sb, ConstraintMode.CASCADE);
|
||||
assertThat(sb.toString()).isEqualTo(" on delete cascade");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -27,7 +27,12 @@ public class TestOrderedList extends BaseTestCase {
|
||||
List<String> sql = LoggedSqlCollector.current();
|
||||
assertThat(sql.size()).isGreaterThan(1);
|
||||
assertThat(sql.get(0)).contains("insert into om_ordered_master");
|
||||
assertThat(sql.get(1)).contains("insert into om_ordered_detail (name, version, sort_order, master_id) values (?,?,?,?)");
|
||||
boolean hasId = sql.get(1).contains(" (id, name");
|
||||
if (hasId) {
|
||||
assertThat(sql.get(1)).contains("insert into om_ordered_detail (id, name, version, sort_order, master_id) values (?,?,?,?,?)");
|
||||
} else {
|
||||
assertThat(sql.get(1)).contains("insert into om_ordered_detail (name, version, sort_order, master_id) values (?,?,?,?)");
|
||||
}
|
||||
|
||||
// update without any changes
|
||||
Ebean.save(master);
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
package org.tests.ddl;
|
||||
|
||||
import io.ebean.annotation.ConstraintMode;
|
||||
import io.ebean.annotation.DbForeignKey;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.ManyToOne;
|
||||
|
||||
@Entity
|
||||
public class DfkCascade {
|
||||
|
||||
@Id
|
||||
long id;
|
||||
|
||||
String name;
|
||||
|
||||
@ManyToOne
|
||||
@DbForeignKey(onDelete = ConstraintMode.CASCADE)
|
||||
DfkCascadeOne one;
|
||||
|
||||
public DfkCascade(String name, DfkCascadeOne one) {
|
||||
this.name = name;
|
||||
this.one = one;
|
||||
}
|
||||
|
||||
public long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public DfkCascadeOne getOne() {
|
||||
return one;
|
||||
}
|
||||
|
||||
public void setOne(DfkCascadeOne one) {
|
||||
this.one = one;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
package org.tests.ddl;
|
||||
|
||||
import javax.persistence.CascadeType;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.OneToMany;
|
||||
import java.util.List;
|
||||
|
||||
@Entity
|
||||
public class DfkCascadeOne {
|
||||
|
||||
@Id
|
||||
long id;
|
||||
|
||||
String name;
|
||||
|
||||
@OneToMany(mappedBy = "one", cascade = CascadeType.ALL)
|
||||
List<DfkCascade> details;
|
||||
|
||||
public DfkCascadeOne(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public List<DfkCascade> getDetails() {
|
||||
return details;
|
||||
}
|
||||
|
||||
public void setDetails(List<DfkCascade> details) {
|
||||
this.details = details;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package org.tests.ddl;
|
||||
|
||||
import io.ebean.annotation.DbForeignKey;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.ManyToOne;
|
||||
|
||||
@Entity
|
||||
public class DfkNone {
|
||||
|
||||
@Id
|
||||
long id;
|
||||
|
||||
String name;
|
||||
|
||||
@ManyToOne
|
||||
@DbForeignKey(noConstraint = true)
|
||||
DfkOne one;
|
||||
|
||||
public DfkNone(String name, DfkOne one) {
|
||||
this.name = name;
|
||||
this.one = one;
|
||||
}
|
||||
|
||||
public long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public DfkOne getOne() {
|
||||
return one;
|
||||
}
|
||||
|
||||
public void setOne(DfkOne one) {
|
||||
this.one = one;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package org.tests.ddl;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
|
||||
@Entity
|
||||
public class DfkOne {
|
||||
|
||||
@Id
|
||||
long id;
|
||||
|
||||
String name;
|
||||
|
||||
public DfkOne(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
package org.tests.ddl;
|
||||
|
||||
import io.ebean.annotation.ConstraintMode;
|
||||
import io.ebean.annotation.DbForeignKey;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.ManyToOne;
|
||||
|
||||
@Entity
|
||||
public class DfkSetNull {
|
||||
|
||||
@Id
|
||||
long id;
|
||||
|
||||
String name;
|
||||
|
||||
@ManyToOne
|
||||
@DbForeignKey(onDelete = ConstraintMode.SET_NULL)
|
||||
DfkOne one;
|
||||
|
||||
public DfkSetNull(String name, DfkOne one) {
|
||||
this.name = name;
|
||||
this.one = one;
|
||||
}
|
||||
|
||||
public long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public DfkOne getOne() {
|
||||
return one;
|
||||
}
|
||||
|
||||
public void setOne(DfkOne one) {
|
||||
this.one = one;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
package org.tests.ddl;
|
||||
|
||||
import io.ebean.BaseTestCase;
|
||||
import io.ebean.Ebean;
|
||||
import org.ebeantest.LoggedSqlCollector;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
public class TestForeignKeyModes extends BaseTestCase {
|
||||
|
||||
@Test
|
||||
public void none() {
|
||||
|
||||
DfkOne one = new DfkOne("one");
|
||||
Ebean.save(one);
|
||||
|
||||
DfkNone none = new DfkNone("none", one);
|
||||
Ebean.save(none);
|
||||
|
||||
// fails unless there is no Foreign key ...
|
||||
Ebean.delete(one);
|
||||
|
||||
DfkNone found = Ebean.find(DfkNone.class, none.getId());
|
||||
assertThat(found).isNotNull();
|
||||
// we still reference one ... even though it does not exist anymore
|
||||
assertThat(found.getOne()).isNotNull();
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void setNullOnDelete() {
|
||||
|
||||
DfkOne one = new DfkOne("one2");
|
||||
Ebean.save(one);
|
||||
|
||||
DfkSetNull other = new DfkSetNull("none", one);
|
||||
Ebean.save(other);
|
||||
|
||||
// success with ... fkey value set to null
|
||||
Ebean.delete(one);
|
||||
|
||||
DfkSetNull found = Ebean.find(DfkSetNull.class, other.getId());
|
||||
assertThat(found).isNotNull();
|
||||
assertThat(found.getOne()).isNull();
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onDeleteCascade() {
|
||||
|
||||
DfkCascadeOne one = new DfkCascadeOne("one3");
|
||||
|
||||
|
||||
DfkCascade other = new DfkCascade("cascade1", one);
|
||||
one.getDetails().add(other);
|
||||
one.getDetails().add(new DfkCascade("cascade2", one));
|
||||
one.getDetails().add(new DfkCascade("cascade3", one));
|
||||
|
||||
Ebean.save(one);
|
||||
|
||||
|
||||
LoggedSqlCollector.start();
|
||||
Ebean.delete(one);
|
||||
|
||||
List<String> sql = LoggedSqlCollector.stop();
|
||||
|
||||
assertThat(sql).hasSize(1);
|
||||
assertThat(sql.get(0)).contains("delete from dfk_cascade_one where id=?");
|
||||
|
||||
DfkCascade found = Ebean.find(DfkCascade.class, other.getId());
|
||||
assertThat(found).isNull();
|
||||
|
||||
}
|
||||
}
|
||||
@@ -35,7 +35,7 @@ public class TestOneToOnePrimaryKeyJoin extends BaseTestCase {
|
||||
OtoPrime found = query.findOne();
|
||||
|
||||
assertThat(found).isNotNull();
|
||||
assertThat(sqlOf(query)).contains("select t0.pid, t0.name, t0.version, t0.pid from oto_prime t0 where t0.pid = ?")
|
||||
assertThat(sqlOf(query, 10)).contains("select t0.pid, t0.name, t0.version, t0.pid from oto_prime t0 where t0.pid = ?")
|
||||
.as("we don't join to oto_prime_extra");
|
||||
|
||||
assertThat(found.getName()).isEqualTo("p" + desc);
|
||||
@@ -47,7 +47,7 @@ public class TestOneToOnePrimaryKeyJoin extends BaseTestCase {
|
||||
OtoPrime oneWith = queryWithFetch.findOne();
|
||||
|
||||
assertThat(oneWith).isNotNull();
|
||||
assertThat(sqlOf(queryWithFetch)).contains("select t0.pid, t0.name, t0.version, t1.eid, t1.extra, t1.version from oto_prime t0 join oto_prime_extra t1 on t1.eid = t0.pid where t0.pid = ?")
|
||||
assertThat(sqlOf(queryWithFetch, 10)).contains("select t0.pid, t0.name, t0.version, t1.eid, t1.extra, t1.version from oto_prime t0 join oto_prime_extra t1 on t1.eid = t0.pid where t0.pid = ?")
|
||||
.as("we join to oto_prime_extra");
|
||||
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ public class TestOneToOnePrimaryKeyJoinBidi extends BaseTestCase {
|
||||
OtoUBPrime found = query.findOne();
|
||||
|
||||
assertThat(found).isNotNull();
|
||||
assertThat(sqlOf(query)).contains("select t0.pid, t0.name, t0.version, t0.pid from oto_ubprime t0 where t0.pid = ?")
|
||||
assertThat(sqlOf(query, 10)).contains("select t0.pid, t0.name, t0.version, t0.pid from oto_ubprime t0 where t0.pid = ?")
|
||||
.as("we don't join to oto_ubprime_extra");
|
||||
|
||||
assertThat(found.getName()).isEqualTo("u" + desc);
|
||||
@@ -47,7 +47,7 @@ public class TestOneToOnePrimaryKeyJoinBidi extends BaseTestCase {
|
||||
OtoUBPrime oneWith = queryWithFetch.findOne();
|
||||
|
||||
assertThat(oneWith).isNotNull();
|
||||
assertThat(sqlOf(queryWithFetch)).contains("select t0.pid, t0.name, t0.version, t1.eid, t1.extra, t1.version, t1.eid from oto_ubprime t0 left join oto_ubprime_extra t1 on t1.eid = t0.pid where t0.pid = ?")
|
||||
assertThat(sqlOf(queryWithFetch, 10)).contains("select t0.pid, t0.name, t0.version, t1.eid, t1.extra, t1.version, t1.eid from oto_ubprime t0 left join oto_ubprime_extra t1 on t1.eid = t0.pid where t0.pid = ?")
|
||||
.as("we join to oto_prime_extra");
|
||||
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ public class TestOneToOnePrimaryKeyJoinOptional extends BaseTestCase {
|
||||
OtoUPrime found = query.findOne();
|
||||
|
||||
assertThat(found).isNotNull();
|
||||
assertThat(sqlOf(query)).contains("select t0.pid, t0.name, t0.version, t0.pid from oto_uprime t0 where t0.pid = ?")
|
||||
assertThat(sqlOf(query, 4)).contains("select t0.pid, t0.name, t0.version, t0.pid from oto_uprime t0 where t0.pid = ?")
|
||||
.as("we don't join to oto_uprime_extra");
|
||||
|
||||
assertThat(found.getName()).isEqualTo("u" + desc);
|
||||
@@ -47,7 +47,7 @@ public class TestOneToOnePrimaryKeyJoinOptional extends BaseTestCase {
|
||||
OtoUPrime oneWith = queryWithFetch.findOne();
|
||||
|
||||
assertThat(oneWith).isNotNull();
|
||||
assertThat(sqlOf(queryWithFetch)).contains("select t0.pid, t0.name, t0.version, t1.eid, t1.extra, t1.version from oto_uprime t0 left join oto_uprime_extra t1 on t1.eid = t0.pid where t0.pid = ?")
|
||||
assertThat(sqlOf(queryWithFetch, 6)).contains("select t0.pid, t0.name, t0.version, t1.eid, t1.extra, t1.version from oto_uprime t0 left join oto_uprime_extra t1 on t1.eid = t0.pid where t0.pid = ?")
|
||||
.as("we join to oto_prime_extra");
|
||||
|
||||
|
||||
|
||||
@@ -7,7 +7,6 @@ import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Table;
|
||||
import javax.validation.constraints.Size;
|
||||
|
||||
import java.time.Instant;
|
||||
|
||||
@Entity
|
||||
@@ -21,7 +20,7 @@ public class EPersonOnline {
|
||||
@Size(max=127)
|
||||
String email;
|
||||
|
||||
boolean online;
|
||||
boolean onlineStatus;
|
||||
|
||||
@WhenModified
|
||||
Instant whenUpdated;
|
||||
@@ -42,12 +41,12 @@ public class EPersonOnline {
|
||||
this.email = email;
|
||||
}
|
||||
|
||||
public boolean isOnline() {
|
||||
return online;
|
||||
public boolean isOnlineStatus() {
|
||||
return onlineStatus;
|
||||
}
|
||||
|
||||
public void setOnline(boolean online) {
|
||||
this.online = online;
|
||||
public void setOnlineStatus(boolean onlineStatus) {
|
||||
this.onlineStatus = onlineStatus;
|
||||
}
|
||||
|
||||
public Instant getWhenUpdated() {
|
||||
|
||||
@@ -15,7 +15,7 @@ public class TestSqlUpdateUpsert extends BaseTestCase {
|
||||
@Test
|
||||
public void h2Merge() {
|
||||
|
||||
String sql = "merge into e_person_online (email, online, when_updated) key(email) values (?, ?, now())";
|
||||
String sql = "merge into e_person_online (email, online_status, when_updated) key(email) values (?, ?, now())";
|
||||
|
||||
String email = "baz@one.com";
|
||||
|
||||
@@ -28,9 +28,9 @@ public class TestSqlUpdateUpsert extends BaseTestCase {
|
||||
EPersonOnline found = Ebean.find(EPersonOnline.class, key);
|
||||
assertThat(found).isNotNull();
|
||||
assertThat(found.getEmail()).isEqualTo(email);
|
||||
assertThat(found.isOnline()).isTrue();
|
||||
assertThat(found.isOnlineStatus()).isTrue();
|
||||
|
||||
String sqlNamed = "merge into e_person_online (email, online, when_updated) key(email) values (:email, :online, now())";
|
||||
String sqlNamed = "merge into e_person_online (email, online_status, when_updated) key(email) values (:email, :online, now())";
|
||||
|
||||
SqlUpdate sqlUpdate2 = Ebean.createSqlUpdate(sqlNamed)
|
||||
.setGetGeneratedKeys(true)
|
||||
@@ -45,7 +45,7 @@ public class TestSqlUpdateUpsert extends BaseTestCase {
|
||||
assertThat(found2).isNotNull();
|
||||
assertThat(found2.getId()).isEqualTo(key);
|
||||
assertThat(found2.getEmail()).isEqualTo(email);
|
||||
assertThat(found2.isOnline()).isFalse();
|
||||
assertThat(found2.isOnlineStatus()).isFalse();
|
||||
assertThat(found2.getWhenUpdated()).isGreaterThan(found.getWhenUpdated());
|
||||
}
|
||||
|
||||
@@ -53,7 +53,7 @@ public class TestSqlUpdateUpsert extends BaseTestCase {
|
||||
@Test
|
||||
public void postgresUpsert() {
|
||||
|
||||
String sql = "insert into e_person_online (email, online, when_updated) values (?, ?, now()) on conflict (email) do update set when_updated=now(), online = ?";
|
||||
String sql = "insert into e_person_online (email, online_status, when_updated) values (?, ?, now()) on conflict (email) do update set when_updated=now(), online_status = ?";
|
||||
|
||||
String email = "foo@one.com";
|
||||
|
||||
@@ -67,10 +67,10 @@ public class TestSqlUpdateUpsert extends BaseTestCase {
|
||||
EPersonOnline found = Ebean.find(EPersonOnline.class, key);
|
||||
assertThat(found).isNotNull();
|
||||
assertThat(found.getEmail()).isEqualTo("foo@one.com");
|
||||
assertThat(found.isOnline()).isTrue();
|
||||
assertThat(found.isOnlineStatus()).isTrue();
|
||||
|
||||
|
||||
String sqlNamed = "insert into e_person_online (email, online, when_updated) values (:email, :online, now()) on conflict (email) do update set when_updated=now(), online = :online";
|
||||
String sqlNamed = "insert into e_person_online (email, online_status, when_updated) values (:email, :online, now()) on conflict (email) do update set when_updated=now(), online_status = :online";
|
||||
SqlUpdate sqlUpdate2 = Ebean.createSqlUpdate(sqlNamed)
|
||||
.setGetGeneratedKeys(true)
|
||||
.setParameter("email", email)
|
||||
@@ -82,7 +82,7 @@ public class TestSqlUpdateUpsert extends BaseTestCase {
|
||||
assertThat(found2).isNotNull();
|
||||
assertThat(found2.getId()).isEqualTo(key);
|
||||
assertThat(found2.getEmail()).isEqualTo("foo@one.com");
|
||||
assertThat(found2.isOnline()).isFalse();
|
||||
assertThat(found2.isOnlineStatus()).isFalse();
|
||||
assertThat(found2.getWhenUpdated()).isGreaterThan(found.getWhenUpdated());
|
||||
|
||||
}
|
||||
@@ -93,7 +93,7 @@ public class TestSqlUpdateUpsert extends BaseTestCase {
|
||||
|
||||
String email = "bar@one.com";
|
||||
|
||||
String sql = "insert into e_person_online (email, online, when_updated) values (?, ?, current_time) on duplicate key update when_updated=current_time, online = ?";
|
||||
String sql = "insert into e_person_online (email, online_status, when_updated) values (?, ?, current_time) on duplicate key update when_updated=current_time, online_status = ?";
|
||||
SqlUpdate sqlUpdate = Ebean.createSqlUpdate(sql)
|
||||
.setGetGeneratedKeys(true)
|
||||
.setParameter(1, email)
|
||||
@@ -106,10 +106,10 @@ public class TestSqlUpdateUpsert extends BaseTestCase {
|
||||
EPersonOnline found = Ebean.find(EPersonOnline.class, key);
|
||||
assertThat(found).isNotNull();
|
||||
assertThat(found.getEmail()).isEqualTo("bar@one.com");
|
||||
assertThat(found.isOnline()).isTrue();
|
||||
assertThat(found.isOnlineStatus()).isTrue();
|
||||
|
||||
|
||||
String sqlNamed = "insert into e_person_online (email, online, when_updated) values (:email, :online, current_time) on duplicate key update when_updated=current_time, online = :online";
|
||||
String sqlNamed = "insert into e_person_online (email, online_status, when_updated) values (:email, :online, current_time) on duplicate key update when_updated=current_time, online_status = :online";
|
||||
SqlUpdate sqlUpdate2 = Ebean.createSqlUpdate(sqlNamed)
|
||||
.setGetGeneratedKeys(true)
|
||||
.setParameter("email", email)
|
||||
@@ -122,7 +122,7 @@ public class TestSqlUpdateUpsert extends BaseTestCase {
|
||||
assertThat(found2).isNotNull();
|
||||
assertThat(found2.getId()).isEqualTo(key);
|
||||
assertThat(found2.getEmail()).isEqualTo("bar@one.com");
|
||||
assertThat(found2.isOnline()).isFalse();
|
||||
assertThat(found2.isOnlineStatus()).isFalse();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user