This fixes OPENJPA-2795 in that generation of indizes for @ManyToOne relations that are also foreign keys can optionally be turned on if so desired. Default behaviour of OpenJPA is unchanged.

This commit contains two new features:
1) A new DB-specific flag DBDictionary#indexPhysicalForeignKeys so that indices for foreign keys will be generated for
database systems that don't automatically create an index for foreign keys.
2) A new boolean property MappingDefaults.IndexPhysicalForeignKeys that will turn the feature from 1) on or off.
By default MappingDefaults.IndexPhysicalForeignKeys is false so that the feature from 1) is disabled.

Note: DBDictionary#indexPhysicalForeignKeys works similar to the pre-existing flag DBDictionary#indexLogicalForeignKeys.

Note: this commit enables FK indices for Oracle and MS SQLServer. Other database systems may benefit, too, and should also be changed.
This commit is contained in:
Robert Mayer 2020-07-06 15:52:27 +02:00 committed by Mark Struberg
parent 119df603b8
commit c13f0b0e13
4 changed files with 46 additions and 8 deletions

View File

@ -61,7 +61,8 @@ public class MappingDefaultsImpl
private int _joinFKAction = ForeignKey.ACTION_NONE;
private int _fkAction = ForeignKey.ACTION_NONE;
private boolean _defer = false;
private boolean _indexFK = true;
private boolean _indexLogicalFK = true;
private boolean _indexPhysicalFK = false;
private boolean _indexDisc = true;
private boolean _indexVers = false;
private boolean _orderLists = true;
@ -248,14 +249,30 @@ public class MappingDefaultsImpl
* Whether to index logical foreign keys by default. Defaults to true.
*/
public boolean getIndexLogicalForeignKeys() {
return _indexFK;
return _indexLogicalFK;
}
/**
* Whether to index logical foreign keys by default. Defaults to true.
*/
public void setIndexLogicalForeignKeys(boolean indexFK) {
_indexFK = indexFK;
_indexLogicalFK = indexFK;
}
/**
* Whether to use DbDictionary specific index on real foreign keys by default.
* Defaults to false i.e. old compatibility behaviour (i.e. no foreign key indices for FKs)
*/
public boolean getIndexPhysicalForeignKeys() {
return _indexPhysicalFK;
}
/**
* Whether to use DbDictionary specific index on real foreign keys by default.
* Defaults to false i.e. old compatibility behaviour (i.e. no foreign key indices for FKs)
*/
public void setIndexPhysicalForeignKeys(boolean indexPhysFKCompat) {
_indexPhysicalFK = indexPhysFKCompat;
}
/**
@ -812,17 +829,25 @@ public class MappingDefaultsImpl
@Override
public Index getJoinIndex(FieldMapping fm, Table table, Column[] cols) {
if (!_indexFK || fm.getJoinForeignKey() == null
|| !fm.getJoinForeignKey().isLogical())
if (!needsFkIndex(fm.getJoinForeignKey())) {
return null;
if (areAllPrimaryKeyColumns(cols))
}
if (areAllPrimaryKeyColumns(cols)) {
return null;
}
Index idx = new Index();
idx.setIdentifier(getIndexName(DBIdentifier.NULL, table, cols));
return idx;
}
private boolean needsFkIndex(ForeignKey fk) {
if (fk == null)
return false;
boolean fkIsLogical = fk.isLogical();
return (_indexLogicalFK && fkIsLogical) || (_indexPhysicalFK && !fkIsLogical && dict.indexPhysicalForeignKeys);
}
/**
* Return whether all the given columns are primary key columns.
*/
@ -868,9 +893,9 @@ public class MappingDefaultsImpl
@Override
public Index getIndex(ValueMapping vm, DBIdentifier name, Table table,
Column[] cols) {
if (!_indexFK || vm.getForeignKey() == null
|| !vm.getForeignKey().isLogical())
if (!needsFkIndex(vm.getForeignKey())) {
return null;
}
if (areAllPrimaryKeyColumns(cols))
return null;

View File

@ -345,6 +345,16 @@ public class DBDictionary
*/
protected BooleanRepresentation booleanRepresentation = BooleanRepresentationFactory.INT_10;
/**
* Whether an index is generated for a relation that is also a foreign key.
* Some database systems (e.g. MySQL) will automatically create an index for a foreign key,
* others (e.g. Oracle, MS-SQL-Server) do not.
*
* See also {@link org.apache.openjpa.jdbc.meta.MappingDefaultsImpl#_indexPhysicalFK}
* which may disable this feature for backwards compatibility.
*/
public boolean indexPhysicalForeignKeys = false;
public int characterColumnSize = 255;
public String arrayTypeName = "ARRAY";
public String bigintTypeName = "BIGINT";

View File

@ -251,6 +251,7 @@ public class OracleDictionary
oracleBlob_empty_lob_Method = getMethodByReflection("oracle.sql.BLOB", "getEmptyBLOB");
oracleClob_isEmptyLob_Method = getMethodByReflection("oracle.sql.CLOB", "isEmptyLob");
indexPhysicalForeignKeys = true; // Oracle does not automatically create an index for a foreign key so we will
}
private Method getMethodByReflection(String className, String methodName, Class<?>... paramTypes) {

View File

@ -80,6 +80,8 @@ public class SQLServerDictionary extends AbstractSQLServerDictionary {
timeWithZoneTypeName = "TIME";
timestampWithZoneTypeName = "DATETIMEOFFSET";
indexPhysicalForeignKeys = true; // MS-SQLServer does not automatically create an index for a foreign key so we will
}
@Override