#1457 - Issue with @ManyToOne with @EmbeddedId where only some columns are insertable or updatable

This commit is contained in:
rob bygrave
2018-07-18 21:29:08 +12:00
parent 2d44d06f36
commit 01541bb208
14 changed files with 318 additions and 22 deletions
@@ -357,14 +357,34 @@ public abstract class BeanPropertyAssoc<T> extends BeanProperty implements STree
* Return true if this association is updateable.
*/
public boolean isUpdateable() {
return tableJoin.columns().length <= 0 || tableJoin.columns()[0].isUpdateable();
TableJoinColumn[] columns = tableJoin.columns();
if (columns.length <= 0) {
return true;
}
for (TableJoinColumn column : columns) {
if (column.isUpdateable()) {
// at least 1 is updatable
return true;
}
}
return false;
}
/**
* Return true if this association is insertable.
*/
public boolean isInsertable() {
return tableJoin.columns().length <= 0 || tableJoin.columns()[0].isInsertable();
TableJoinColumn[] columns = tableJoin.columns();
if (columns.length <= 0) {
return true;
}
for (TableJoinColumn column : columns) {
if (column.isInsertable()) {
// at least 1 is insertable
return true;
}
}
return false;
}
/**
@@ -443,16 +463,18 @@ public abstract class BeanPropertyAssoc<T> extends BeanProperty implements STree
String matchColumn = col.getForeignDbColumn();
String localColumn = col.getLocalDbColumn();
String localSqlFormula = col.getLocalSqlFormula();
boolean insertable = col.isInsertable();
boolean updateable = col.isUpdateable();
for (int j = 0; j < props.length; j++) {
if (props[j].getDbColumn().equalsIgnoreCase(matchColumn)) {
return new ImportedIdSimple(owner, localColumn, localSqlFormula, props[j], j);
return new ImportedIdSimple(owner, localColumn, localSqlFormula, props[j], j, insertable, updateable);
}
}
for (int j = 0; j < others.length; j++) {
if (others[j].getDbColumn().equalsIgnoreCase(matchColumn)) {
return new ImportedIdSimple(owner, localColumn, localSqlFormula, others[j], j + props.length);
return new ImportedIdSimple(owner, localColumn, localSqlFormula, others[j], j + props.length, insertable, updateable);
}
}
@@ -64,8 +64,11 @@ public class ImportedIdEmbedded implements ImportedId {
@Override
public void dmlAppend(GenerateDmlRequest request) {
boolean update = request.isUpdate();
for (ImportedIdSimple anImported : imported) {
request.appendColumn(anImported.localDbColumn);
if (anImported.isInclude(update)) {
request.appendColumn(anImported.localDbColumn);
}
}
}
@@ -100,30 +103,28 @@ public class ImportedIdEmbedded implements ImportedId {
@Override
public Object bind(BindableRequest request, EntityBean bean) throws SQLException {
Object embeddedId = null;
if (bean != null) {
embeddedId = foreignAssocOne.getValue(bean);
}
Object embeddedId = (bean == null) ? null : foreignAssocOne.getValue(bean);
boolean update = request.isUpdate();
if (embeddedId == null) {
for (ImportedIdSimple anImported : imported) {
if (anImported.owner.isUpdateable()) {
if (anImported.isInclude(update)) {
request.bind(null, anImported.foreignProperty);
}
}
// return anything non-null to skip a derived relationship update
return Object.class;
} else {
EntityBean embedded = (EntityBean) embeddedId;
for (ImportedIdSimple anImported : imported) {
if (anImported.owner.isUpdateable()) {
if (anImported.isInclude(update)) {
Object scalarValue = anImported.foreignProperty.getValue(embedded);
request.bind(scalarValue, anImported.foreignProperty);
}
}
return embedded;
}
// hmmm, not worrying about this just yet
return null;
}
@Override
@@ -47,15 +47,32 @@ public final class ImportedIdSimple implements ImportedId, Comparable<ImportedId
protected final int position;
public ImportedIdSimple(BeanPropertyAssoc<?> owner, String localDbColumn, String localSqlFormula, BeanProperty foreignProperty, int position) {
/**
* If true include in insert.
*/
private final boolean insertable;
/**
* If true include in update.
*/
private final boolean updateable;
public ImportedIdSimple(BeanPropertyAssoc<?> owner, String localDbColumn, String localSqlFormula, BeanProperty foreignProperty, int position,
boolean insertable, boolean updateable) {
this.owner = owner;
this.localDbColumn = InternString.intern(localDbColumn);
this.localSqlFormula = InternString.intern(localSqlFormula);
this.foreignProperty = foreignProperty;
this.position = position;
this.insertable = insertable;
this.updateable = updateable;
this.logicalName = InternString.intern(owner.getName() + "." + foreignProperty.getName());
}
public ImportedIdSimple(BeanPropertyAssoc<?> owner, String localDbColumn, String localSqlFormula, BeanProperty foreignProperty, int position) {
this(owner, localDbColumn, localSqlFormula, foreignProperty, position, true, true);
}
/**
* Return the list as an array sorted into the same order as the Bean Properties.
*/
@@ -68,6 +85,13 @@ public final class ImportedIdSimple implements ImportedId, Comparable<ImportedId
return importedIds;
}
/**
* Return true if it should be included in the update (or insert).
*/
public boolean isInclude(boolean update) {
return (update) ? updateable : insertable;
}
@Override
public boolean equals(Object obj) {
// remove FindBugs warning
@@ -19,6 +19,11 @@ public class DeleteHandler extends DmlHandler {
this.meta = meta;
}
@Override
public boolean isUpdate() {
return false;
}
/**
* Generate and bind the delete statement.
*/
@@ -29,10 +29,6 @@ public class GenerateDmlRequest {
return this;
}
public void appendColumnIsNull(String column) {
appendColumn(column, IS_NULL);
}
public void appendColumn(String column) {
//String bind = (insertMode > 0) ? "?" : "=?";
appendColumn(column, "?");
@@ -91,4 +87,7 @@ public class GenerateDmlRequest {
this.prefix2 = ", ";
}
public boolean isUpdate() {
return insertMode == 0;
}
}
@@ -50,6 +50,11 @@ public class InsertHandler extends DmlHandler {
this.concatinatedKey = meta.isConcatenatedKey();
}
@Override
public boolean isUpdate() {
return false;
}
/**
* Generate and bind the insert statement.
*/
@@ -22,6 +22,11 @@ public class UpdateHandler extends DmlHandler {
this.meta = meta;
}
@Override
public boolean isUpdate() {
return true;
}
/**
* Generate and bind the update statement.
*/
@@ -59,4 +59,8 @@ public interface BindableRequest {
*/
long now();
/**
* Return true if this is an update request.
*/
boolean isUpdate();
}
@@ -19,9 +19,7 @@ public class FactoryAssocOnes {
*/
public void create(List<Bindable> list, BeanDescriptor<?> desc, DmlMode mode) {
BeanPropertyAssocOne<?>[] ones = desc.propertiesOneImported();
for (BeanPropertyAssocOne<?> one : ones) {
for (BeanPropertyAssocOne<?> one : desc.propertiesOneImported()) {
if (!one.isImportedPrimaryKey()) {
switch (mode) {
case INSERT: