Support for @Identity - initial refactor to add IdentityMode

This commit is contained in:
rob bygrave
2020-03-03 22:36:27 +13:00
parent ddf3c753d6
commit eb765056fd
13 changed files with 389 additions and 338 deletions
+1 -1
View File
@@ -87,7 +87,7 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-annotation</artifactId>
<version>6.8</version>
<version>6.9</version>
</dependency>
<dependency>
@@ -35,6 +35,11 @@ public enum IdType {
* Used when the key is a compound key or lookup table code.
* </p>
*/
EXTERNAL
EXTERNAL,
/**
* Auto mapping to platform preferred identity strategy.
*/
AUTO
}
+1 -7
View File
@@ -8,12 +8,11 @@ import io.ebean.event.BeanPersistListener;
import io.ebean.event.BeanQueryAdapter;
import io.ebeanservice.docstore.api.mapping.DocumentMapping;
import javax.annotation.Nonnull;
import java.util.Collection;
import java.util.List;
import java.util.function.Consumer;
import javax.annotation.Nonnull;
/**
* Information and methods on BeanDescriptors made available to plugins.
*/
@@ -156,11 +155,6 @@ public interface BeanType<T> {
*/
IdType getIdType();
/**
* Return the sequence name associated to this entity bean type (if there is one).
*/
String getSequenceName();
/**
* Return true if this bean type has doc store backing.
*/
@@ -385,7 +385,7 @@ public class BaseTableDdl implements TableDdl {
int allocate = toInt(createTable.getSequenceAllocate());
String seqName = explicitSequenceName;
if (seqName == null) {
if (seqName == null || seqName.isEmpty()) {
seqName = namingConvention.getSequenceName(createTable.getName(), pk);
}
@@ -11,13 +11,14 @@ import io.ebeaninternal.dbmigration.migration.DropColumn;
import io.ebeaninternal.dbmigration.migration.DropHistoryTable;
import io.ebeaninternal.dbmigration.migration.DropTable;
import io.ebeaninternal.dbmigration.migration.ForeignKey;
import io.ebeaninternal.dbmigration.migration.IdentityType;
import io.ebeaninternal.dbmigration.migration.UniqueConstraint;
import io.ebeaninternal.server.deploy.BeanDescriptor;
import io.ebeaninternal.server.deploy.IdentityMode;
import io.ebeaninternal.server.deploy.BeanProperty;
import io.ebeaninternal.server.deploy.PartitionMeta;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
@@ -27,6 +28,8 @@ import java.util.Map;
import java.util.Set;
import static io.ebeaninternal.dbmigration.ddlgeneration.platform.SplitColumns.split;
import static io.ebeaninternal.dbmigration.model.MTableIdentity.fromCreateTable;
import static io.ebeaninternal.dbmigration.model.MTableIdentity.toCreateTable;
/**
* Holds the logical model for a given Table and everything associated to it.
@@ -84,18 +87,7 @@ public class MTable {
*/
private String indexTablespace;
/**
* If set then this overrides the platform default so for UUID generated values
* or DB's supporting both sequences and autoincrement.
*/
private IdentityType identityType;
/**
* DB sequence name.
*/
private String sequenceName;
private int sequenceInitial;
private int sequenceAllocate;
private IdentityMode identityMode;
/**
* If set to true this table should has history support.
@@ -130,6 +122,29 @@ public class MTable {
private List<String> droppedColumns = new ArrayList<>();
public MTable(BeanDescriptor<?> descriptor) {
this.name = descriptor.getBaseTable();
this.identityMode = descriptor.getIdentityMode();
this.storageEngine = descriptor.getStorageEngine();
this.partitionMeta = descriptor.getPartitionMeta();
this.comment = descriptor.getDbComment();
if (descriptor.isHistorySupport()) {
withHistory = true;
BeanProperty whenCreated = descriptor.getWhenCreatedProperty();
if (whenCreated != null) {
whenCreatedColumn = whenCreated.getDbColumn();
}
}
}
/**
* Construct for element collection or intersection table.
*/
public MTable(String name) {
this.name = name;
this.identityMode = IdentityMode.none();
}
/**
* Create a copy of this table structure as a 'draft' table.
* <p>
@@ -143,7 +158,7 @@ public class MTable {
draftTable.whenCreatedColumn = whenCreatedColumn;
// compoundKeys
// compoundUniqueConstraints
draftTable.identityType = identityType;
draftTable.identityMode = identityMode;
for (MColumn col : allColumns()) {
draftTable.addColumn(col.copyForDraft());
@@ -164,9 +179,7 @@ public class MTable {
this.indexTablespace = createTable.getIndexTablespace();
this.withHistory = Boolean.TRUE.equals(createTable.isWithHistory());
this.draft = Boolean.TRUE.equals(createTable.isDraft());
this.sequenceName = createTable.getSequenceName();
this.sequenceInitial = toInt(createTable.getSequenceInitial());
this.sequenceAllocate = toInt(createTable.getSequenceAllocate());
this.identityMode = fromCreateTable(createTable);
List<Column> cols = createTable.getColumn();
for (Column column : cols) {
addColumn(column);
@@ -194,13 +207,6 @@ public class MTable {
addForeignKey(foreignKey);
}
/**
* Construct typically from EbeanServer meta data.
*/
public MTable(String name) {
this.name = name;
}
/**
* Return the DropTable migration for this table.
*/
@@ -208,7 +214,7 @@ public class MTable {
DropTable dropTable = new DropTable();
dropTable.setName(name);
// we must add pk col name & sequence name, as we have to delete the sequence also.
if (identityType != IdentityType.GENERATOR && identityType != IdentityType.EXTERNAL) {
if (identityMode.isDatabaseIdentity()) {
String pkCol = null;
for (MColumn column : columns.values()) {
if (column.isPrimaryKey()) {
@@ -222,7 +228,7 @@ public class MTable {
}
if (pkCol != null) {
dropTable.setSequenceCol(pkCol);
dropTable.setSequenceName(sequenceName);
dropTable.setSequenceName(identityMode.getSequenceName());
}
}
return dropTable;
@@ -244,10 +250,7 @@ public class MTable {
createTable.setStorageEngine(storageEngine);
createTable.setTablespace(tablespace);
createTable.setIndexTablespace(indexTablespace);
createTable.setSequenceName(sequenceName);
createTable.setSequenceInitial(toBigInteger(sequenceInitial));
createTable.setSequenceAllocate(toBigInteger(sequenceAllocate));
createTable.setIdentityType(identityType);
toCreateTable(identityMode, createTable);
if (withHistory) {
createTable.setWithHistory(Boolean.TRUE);
}
@@ -458,10 +461,6 @@ public class MTable {
this.comment = comment;
}
public void setStorageEngine(String storageEngine) {
this.storageEngine = storageEngine;
}
public String getTablespace() {
return tablespace;
}
@@ -519,36 +518,10 @@ public class MTable {
return compoundKeys;
}
public void setSequenceName(String sequenceName) {
this.sequenceName = sequenceName;
}
public void setSequenceInitial(int sequenceInitial) {
this.sequenceInitial = sequenceInitial;
}
public void setSequenceAllocate(int sequenceAllocate) {
this.sequenceAllocate = sequenceAllocate;
}
public void setWhenCreatedColumn(String whenCreatedColumn) {
this.whenCreatedColumn = whenCreatedColumn;
}
public String getWhenCreatedColumn() {
return whenCreatedColumn;
}
/**
* Set the identity type to use for this table.
* <p>
* If set then this overrides the platform default so for UUID generated values
* or DB's supporting both sequences and autoincrement.
*/
public void setIdentityType(IdentityType identityType) {
this.identityType = identityType;
}
/**
* Return the list of columns that make the primary key.
*/
@@ -671,14 +644,6 @@ public class MTable {
droppedColumns.add(columnName);
}
private int toInt(BigInteger value) {
return (value == null) ? 0 : value.intValue();
}
private BigInteger toBigInteger(int value) {
return (value == 0) ? null : BigInteger.valueOf(value);
}
/**
* Check if there are duplicate foreign keys.
* <p>
@@ -774,10 +739,6 @@ public class MTable {
}
}
public void setPartitionMeta(PartitionMeta partitionMeta) {
this.partitionMeta = partitionMeta;
}
/**
* Clear foreign key as this element collection table logically references
* back to multiple tables.
@@ -0,0 +1,91 @@
package io.ebeaninternal.dbmigration.model;
import io.ebean.annotation.IdentityGenerated;
import io.ebean.config.dbplatform.IdType;
import io.ebeaninternal.dbmigration.migration.CreateTable;
import io.ebeaninternal.dbmigration.migration.IdentityType;
import io.ebeaninternal.server.deploy.IdentityMode;
import java.math.BigInteger;
/**
* Helper to convert between IdentityMode and CreateTable
*/
class MTableIdentity {
/**
* Return the IdentityMode from CreateTable.
*/
static IdentityMode fromCreateTable(CreateTable createTable) {
IdType type = fromType(createTable.getIdentityType());
int start = toInt(createTable.getSequenceInitial());
int increment = toInt(createTable.getSequenceAllocate());
String seqName = createTable.getSequenceName();
return new IdentityMode(type, IdentityGenerated.AUTO, start, increment, seqName);
}
/**
* Set the IdentityMode to the CreateTable model.
*/
public static void toCreateTable(IdentityMode identityMode, CreateTable createTable) {
if (!identityMode.isPlatformDefault()) {
createTable.setIdentityType(toType(identityMode.getIdType()));
}
final String seqName = identityMode.getSequenceName();
if (seqName != null && !seqName.isEmpty()) {
createTable.setSequenceName(seqName);
}
createTable.setSequenceInitial(toBigInteger(identityMode.getStart()));
createTable.setSequenceAllocate(toBigInteger(identityMode.getIncrement()));
}
private static IdType fromType(IdentityType type) {
if (type == null) {
return IdType.AUTO;
}
switch (type) {
case DEFAULT:
return IdType.AUTO;
case SEQUENCE:
return IdType.SEQUENCE;
case IDENTITY:
return IdType.IDENTITY;
case GENERATOR:
return IdType.GENERATOR;
case EXTERNAL:
return IdType.EXTERNAL;
}
return IdType.AUTO;
}
private static IdentityType toType(IdType type) {
if (type == null) {
// intersection or element collection table
return null;
}
switch (type) {
case SEQUENCE:
return IdentityType.SEQUENCE;
case IDENTITY:
return IdentityType.IDENTITY;
case EXTERNAL:
return IdentityType.EXTERNAL;
case GENERATOR:
return IdentityType.GENERATOR;
}
return null;
}
private static int toInt(BigInteger value) {
return (value == null) ? 0 : value.intValue();
}
private static BigInteger toBigInteger(int value) {
return (value == 0) ? null : BigInteger.valueOf(value);
}
}
@@ -1,13 +1,10 @@
package io.ebeaninternal.dbmigration.model.build;
import io.ebean.config.dbplatform.DbPlatformType;
import io.ebean.config.dbplatform.IdType;
import io.ebeaninternal.dbmigration.migration.IdentityType;
import io.ebeaninternal.dbmigration.model.MColumn;
import io.ebeaninternal.dbmigration.model.MTable;
import io.ebeaninternal.dbmigration.model.visitor.BeanVisitor;
import io.ebeaninternal.server.deploy.BeanDescriptor;
import io.ebeaninternal.server.deploy.BeanProperty;
import io.ebeaninternal.server.deploy.InheritInfo;
/**
@@ -35,19 +32,7 @@ public class ModelBuildBeanVisitor implements BeanVisitor {
return null;
}
MTable table = new MTable(descriptor.getBaseTable());
table.setStorageEngine(descriptor.getStorageEngine());
table.setPartitionMeta(descriptor.getPartitionMeta());
table.setComment(descriptor.getDbComment());
if (descriptor.isHistorySupport()) {
table.setWithHistory(true);
BeanProperty whenCreated = descriptor.getWhenCreatedProperty();
if (whenCreated != null) {
table.setWhenCreatedColumn(whenCreated.getDbColumn());
}
}
setIdentity(descriptor, table);
MTable table = new MTable(descriptor);
// add the table to the model
ctx.addTable(table);
@@ -66,43 +51,4 @@ public class ModelBuildBeanVisitor implements BeanVisitor {
return new ModelBuildPropertyVisitor(ctx, table, descriptor);
}
/**
* Set the identity type to use for this table.
* <p>
* Takes into account the requested identity type and the underlying support in the
* database platform.
* </p>
*/
private void setIdentity(BeanDescriptor<?> descriptor, MTable table) {
if (IdType.GENERATOR == descriptor.getIdType()) {
// explicit generator like UUID
table.setIdentityType(IdentityType.GENERATOR);
return;
}
if (IdType.EXTERNAL == descriptor.getIdType()) {
// externally defined code (lookup table, ISO country code etc)
table.setIdentityType(IdentityType.EXTERNAL);
return;
}
int initialValue = descriptor.getSequenceInitialValue();
int allocationSize = descriptor.getSequenceAllocationSize();
if (!descriptor.isIdTypePlatformDefault() || initialValue > 0 || allocationSize > 0) {
// explicitly set to use sequence or identity (generally not recommended practice)
if (IdType.IDENTITY == descriptor.getIdType()) {
if (!descriptor.isIdTypePlatformDefault()) {
table.setIdentityType(IdentityType.IDENTITY);
}
} else {
// explicit sequence defined
table.setIdentityType(IdentityType.SEQUENCE);
table.setSequenceName(descriptor.getSequenceName());
table.setSequenceInitial(initialValue);
table.setSequenceAllocate(allocationSize);
}
}
}
}
@@ -164,18 +164,9 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType {
*/
private final boolean idGeneratedValue;
private final boolean idTypePlatformDefault;
private final PlatformIdGenerator idGenerator;
/**
* The database sequence name (optional).
*/
private final String sequenceName;
private final int sequenceInitialValue;
private final int sequenceAllocationSize;
private final IdentityMode identityMode;
/**
* SQL used to return last inserted id. Used for Identity columns where
@@ -456,13 +447,10 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType {
this.changeLogFilter = deploy.getChangeLogFilter();
this.defaultSelectClause = deploy.getDefaultSelectClause();
this.idType = deploy.getIdType();
this.identityMode = deploy.getIdentityMode();
this.idType = identityMode.getIdType();
this.idGeneratedValue = deploy.isIdGeneratedValue();
this.idTypePlatformDefault = deploy.isIdTypePlatformDefault();
this.idGenerator = deploy.getIdGenerator();
this.sequenceName = deploy.getSequenceName();
this.sequenceInitialValue = deploy.getSequenceInitialValue();
this.sequenceAllocationSize = deploy.getSequenceAllocationSize();
this.selectLastInsertedId = deploy.getSelectLastInsertedId();
this.selectLastInsertedIdDraft = deploy.getSelectLastInsertedIdDraft();
this.concurrencyMode = deploy.getConcurrencyMode();
@@ -3158,33 +3146,8 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType {
return idGeneratedValue;
}
/**
* Return true if the identity is the platform default (not explicitly set).
*/
public boolean isIdTypePlatformDefault() {
return idTypePlatformDefault;
}
/**
* Return the sequence name.
*/
@Override
public String getSequenceName() {
return sequenceName;
}
/**
* Return the sequence initial value.
*/
public int getSequenceInitialValue() {
return sequenceInitialValue;
}
/**
* Return the sequence allocation size.
*/
public int getSequenceAllocationSize() {
return sequenceAllocationSize;
public IdentityMode getIdentityMode() {
return identityMode;
}
/**
@@ -1354,42 +1354,39 @@ public class BeanDescriptorManager implements BeanDescriptorMap {
return;
}
if (IdType.SEQUENCE == desc.getIdType() && !dbIdentity.isSupportsSequence()) {
final IdentityMode identityMode = desc.getIdentityMode();
if (identityMode.isSequence() && !dbIdentity.isSupportsSequence()) {
// explicit sequence but not supported by the DatabasePlatform
logger.info("Explicit sequence on " + desc.getFullName() + " but not supported by DB Platform - ignored");
desc.setIdType(null);
identityMode.setIdType(IdType.AUTO);
}
if (IdType.IDENTITY == desc.getIdType() && !dbIdentity.isSupportsIdentity()) {
if (identityMode.isIdentity() && !dbIdentity.isSupportsIdentity()) {
// explicit identity but not supported by the DatabasePlatform
logger.info("Explicit Identity on " + desc.getFullName() + " but not supported by DB Platform - ignored");
desc.setIdType(null);
identityMode.setIdType(IdType.AUTO);
}
if (desc.getIdType() == null) {
if (identityMode.isAuto()) {
if (desc.isPrimaryKeyCompoundOrNonNumeric()) {
// assuming that this is a user supplied key like ISO country code or ISO currency code or lookup table code
logger.debug("Expecting user defined identity on {} - not using db sequence or autoincrement", desc.getFullName());
desc.setIdType(IdType.EXTERNAL);
identityMode.setIdType(IdType.EXTERNAL);
return;
}
if (desc.isIdGeneratedValue() || serverConfig.isIdGeneratorAutomatic()) {
// use IDENTITY or SEQUENCE based on platform
desc.setIdType(dbIdentity.getIdType());
desc.setIdTypePlatformDefault();
identityMode.setPlatformType(dbIdentity.getIdType());
} else {
// externally/application supplied Id values
desc.setIdType(IdType.EXTERNAL);
identityMode.setIdType(IdType.EXTERNAL);
return;
}
}
if (desc.getBaseTable() == null) {
// no base table so not going to set Identity
// of sequence information
// no base table so not going to set Identity or sequence information
return;
}
if (IdType.IDENTITY == desc.getIdType()) {
if (identityMode.isIdentity()) {
// used when getGeneratedKeys is not supported (SQL Server 2000, SAP Hana)
String selectLastInsertedId = dbIdentity.getSelectLastInsertedId(desc.getBaseTable());
String selectLastInsertedIdDraft = (!desc.isDraftable()) ? selectLastInsertedId : dbIdentity.getSelectLastInsertedId(desc.getDraftTable());
@@ -1397,21 +1394,21 @@ public class BeanDescriptorManager implements BeanDescriptorMap {
return;
}
if (IdType.SEQUENCE == desc.getIdType()) {
String seqName = desc.getIdGeneratorName();
if (seqName != null) {
logger.debug("explicit sequence {} on {}", seqName, desc.getFullName());
} else {
if (identityMode.isSequence()) {
String seqName = identityMode.getSequenceName();
if (seqName == null || seqName.isEmpty()) {
String primaryKeyColumn = desc.getSinglePrimaryKeyColumn();
// use namingConvention to define sequence name
seqName = namingConvention.getSequenceName(desc.getBaseTable(), primaryKeyColumn);
}
if (databasePlatform.isSequenceBatchMode()) {
// use sequence next step 1 as we are going to batch fetch them instead
desc.setSequenceAllocationSize(1);
desc.setIdentitySequenceBatchMode();
}
int stepSize = identityMode.getIncrement();
if (stepSize == 0) {
stepSize = 50;
}
int stepSize = desc.getSequenceAllocationSize();
desc.setIdGenerator(createSequenceIdGenerator(seqName, stepSize));
}
}
@@ -0,0 +1,154 @@
package io.ebeaninternal.server.deploy;
import io.ebean.annotation.IdentityGenerated;
import io.ebean.annotation.IdentityType;
import io.ebean.config.dbplatform.IdType;
public class IdentityMode {
public static IdentityMode auto() {
return new IdentityMode(IdType.AUTO);
}
public static IdentityMode none() {
return new IdentityMode(null);
}
public static IdType idType(IdentityType type) {
switch (type) {
case AUTO:
return IdType.AUTO;
case SEQUENCE:
return IdType.SEQUENCE;
case IDENTITY:
return IdType.IDENTITY;
case APPLICATION:
return IdType.EXTERNAL;
default:
throw new IllegalStateException("type " + type + " not expected?");
}
}
private IdType type;
private IdentityGenerated generated;
private int start;
private int increment;
private int cache;
private String sequenceName;
private boolean platformDefault;
public IdentityMode(IdType type, IdentityGenerated generated, int start, int increment, String seqName) {
this.type = type;
this.generated = generated;
this.start = start;
this.increment = increment;
this.sequenceName = seqName;
}
/**
* Create from <code>@SequenceGenerator</code> annotation.
*/
public IdentityMode(int initialValue, int allocationSize, String sequenceName) {
this.type = IdType.AUTO;
this.generated = IdentityGenerated.AUTO;
this.sequenceName = sequenceName;
this.start = initialValue;
this.increment = allocationSize;
this.cache = 0;
}
private IdentityMode(IdType type) {
this.type = type;
this.generated = IdentityGenerated.AUTO;
this.sequenceName = "";
this.start = 0;
this.increment = 0;
this.cache = 0;
}
public void setPlatformType(IdType type) {
this.type = type;
this.platformDefault = true;
}
public void setSequence(int initialValue, int allocationSize, String sequenceName) {
this.start = initialValue;
this.increment = allocationSize;
this.sequenceName = sequenceName;
}
public void setSequenceGenerator(String genName) {
if (sequenceName == null || sequenceName.isEmpty()) {
sequenceName = genName;
}
}
public void setSequenceBatchMode() {
this.increment = 1;
}
public void setIdType(IdType type) {
this.type = type;
}
public void setStart(int start) {
this.start = start;
}
public void setIncrement(int increment) {
this.increment = increment;
}
public void setSequenceName(String sequenceName) {
this.sequenceName = sequenceName;
}
public boolean isPlatformDefault() {
return platformDefault;
}
public IdType getIdType() {
return type;
}
public IdentityGenerated getGenerated() {
return generated;
}
public int getStart() {
return start;
}
public int getIncrement() {
return increment;
}
public int getCache() {
return cache;
}
public String getSequenceName() {
return sequenceName;
}
public boolean isSequence() {
return type == IdType.SEQUENCE;
}
public boolean isIdentity() {
return type == IdType.IDENTITY;
}
public boolean isExternal() {
return type == IdType.EXTERNAL;
}
public boolean isAuto() {
return type == IdType.AUTO;
}
public boolean isDatabaseIdentity() {
return type != IdType.EXTERNAL && type != IdType.GENERATOR;
}
}
@@ -25,6 +25,7 @@ import io.ebeaninternal.server.deploy.ChainedBeanPostConstructListener;
import io.ebeaninternal.server.deploy.ChainedBeanPostLoad;
import io.ebeaninternal.server.deploy.ChainedBeanQueryAdapter;
import io.ebeaninternal.server.deploy.DeployPropertyParserMap;
import io.ebeaninternal.server.deploy.IdentityMode;
import io.ebeaninternal.server.deploy.IndexDefinition;
import io.ebeaninternal.server.deploy.InheritInfo;
import io.ebeaninternal.server.deploy.PartitionMeta;
@@ -85,24 +86,11 @@ public class DeployBeanDescriptor<T> {
private DeployBeanProperty orderColumn;
/**
* Type of Identity generation strategy used.
*/
private IdType idType;
private Class<?> idClass;
private DeployBeanPropertyAssocOne<?> idClassProperty;
/**
* Set to true if the identity is default for the platform.
*/
private boolean idTypePlatformDefault;
/**
* The name of an IdGenerator (optional).
*/
private String idGeneratorName;
private IdentityMode identityMode = IdentityMode.auto();
private PlatformIdGenerator idGenerator;
@@ -111,15 +99,6 @@ public class DeployBeanDescriptor<T> {
*/
private boolean idGeneratedValue;
/**
* The database sequence name (optional).
*/
private String sequenceName;
private int sequenceInitialValue;
private int sequenceAllocationSize = 50;
/**
* Used with Identity columns but no getGeneratedKeys support.
*/
@@ -244,8 +223,7 @@ public class DeployBeanDescriptor<T> {
*/
public void setPrimaryKeyJoin(TableJoin join) {
this.primaryKeyJoin = join;
this.idType = IdType.EXTERNAL;
this.idGeneratorName = null;
this.identityMode.setIdType(IdType.EXTERNAL);
this.idGenerator = null;
}
@@ -399,20 +377,40 @@ public class DeployBeanDescriptor<T> {
return entityType;
}
public void setSequenceInitialValue(int sequenceInitialValue) {
this.sequenceInitialValue = sequenceInitialValue;
public IdentityMode getIdentityMode() {
return identityMode;
}
public void setSequenceAllocationSize(int sequenceAllocationSize) {
this.sequenceAllocationSize = sequenceAllocationSize;
/**
* Set from <code>@Identity</code>
*/
public void setIdentityMode(IdentityMode identityMode) {
this.identityMode = identityMode;
}
public int getSequenceInitialValue() {
return sequenceInitialValue;
/**
* Set from <code>@Sequence</code>
*/
public void setIdentitySequence(int initialValue, int allocationSize, String seqName) {
identityMode.setSequence(initialValue, allocationSize, seqName);
}
public int getSequenceAllocationSize() {
return sequenceAllocationSize;
/**
* Potentially set sequence name from <code>@GeneratedValue</code>.
*/
public void setIdentitySequenceGenerator(String genName) {
identityMode.setSequenceGenerator(genName);
}
/**
* Set use of Ebean side sequence batching.
*/
public void setIdentitySequenceBatchMode() {
identityMode.setSequenceBatchMode();
}
public void setIdentityType(IdType type) {
this.identityMode.setIdType(type);
}
public String[] getProperties() {
@@ -760,48 +758,6 @@ public class DeployBeanDescriptor<T> {
this.name = name;
}
/**
* Return the identity generation type.
*/
public IdType getIdType() {
return idType;
}
/**
* Set the identity generation type.
*/
public void setIdType(IdType idType) {
this.idType = idType;
}
/**
* Set when the identity type is the platform default.
*/
public void setIdTypePlatformDefault() {
this.idTypePlatformDefault = true;
}
/**
* Return true when the identity is the platform default.
*/
public boolean isIdTypePlatformDefault() {
return idTypePlatformDefault;
}
/**
* Return the DB sequence name (can be null).
*/
public String getSequenceName() {
return sequenceName;
}
/**
* Set the DB sequence name.
*/
private void setSequenceName(String sequenceName) {
this.sequenceName = sequenceName;
}
/**
* Return the SQL used to return the last inserted Id.
* <p>
@@ -824,21 +780,6 @@ public class DeployBeanDescriptor<T> {
this.selectLastInsertedIdDraft = selectLastInsertedIdDraft;
}
/**
* Return the name of the IdGenerator that should be used with this type of
* bean. A null value could be used to specify the 'default' IdGenerator.
*/
public String getIdGeneratorName() {
return idGeneratorName;
}
/**
* Set the name of the IdGenerator that should be used with this type of bean.
*/
public void setIdGeneratorName(String idGeneratorName) {
this.idGeneratorName = idGeneratorName;
}
/**
* Return the actual IdGenerator for this bean type (can be null).
*/
@@ -851,9 +792,6 @@ public class DeployBeanDescriptor<T> {
*/
public void setIdGenerator(PlatformIdGenerator idGenerator) {
this.idGenerator = idGenerator;
if (idGenerator != null && idGenerator.isDbSequence()) {
setSequenceName(idGenerator.getName());
}
}
/**
@@ -871,25 +809,25 @@ public class DeployBeanDescriptor<T> {
}
/**
* Assign the standard UUID generator.
* Assign the standard UUID generator if one has not been set.
*/
public void setUuidGenerator() {
this.idType = IdType.EXTERNAL;
this.idGeneratorName = PlatformIdGenerator.AUTO_UUID;
if (idGenerator == null) {
this.identityMode.setIdType(IdType.EXTERNAL);
switch (serverConfig.getUuidVersion()) {
case VERSION1:
this.idGenerator = UuidV1IdGenerator.getInstance(serverConfig.getUuidStateFile());
break;
switch (serverConfig.getUuidVersion()) {
case VERSION1:
this.idGenerator = UuidV1IdGenerator.getInstance(serverConfig.getUuidStateFile());
break;
case VERSION1RND:
this.idGenerator = UuidV1RndIdGenerator.INSTANCE;
break;
case VERSION1RND:
this.idGenerator = UuidV1RndIdGenerator.INSTANCE;
break;
case VERSION4:
default:
this.idGenerator = UuidV4IdGenerator.INSTANCE;
break;
case VERSION4:
default:
this.idGenerator = UuidV4IdGenerator.INSTANCE;
break;
}
}
}
@@ -897,8 +835,7 @@ public class DeployBeanDescriptor<T> {
* Assign a custom external IdGenerator.
*/
public void setCustomIdGenerator(PlatformIdGenerator idGenerator) {
this.idType = IdType.EXTERNAL;
this.idGeneratorName = idGenerator.getName();
this.identityMode.setIdType(IdType.EXTERNAL);
this.idGenerator = idGenerator;
}
@@ -951,7 +888,6 @@ public class DeployBeanDescriptor<T> {
* is non-numeric (and hence not suitable for db identity or sequence.
*/
public boolean isPrimaryKeyCompoundOrNonNumeric() {
DeployBeanProperty id = idProperty();
if (id == null) {
return false;
@@ -5,9 +5,9 @@ import io.ebean.annotation.CreatedTimestamp;
import io.ebean.annotation.DbArray;
import io.ebean.annotation.DbComment;
import io.ebean.annotation.DbDefault;
import io.ebean.annotation.DbMap;
import io.ebean.annotation.DbJson;
import io.ebean.annotation.DbJsonB;
import io.ebean.annotation.DbMap;
import io.ebean.annotation.DbMigration;
import io.ebean.annotation.DocCode;
import io.ebean.annotation.DocEmbedded;
@@ -21,11 +21,11 @@ import io.ebean.annotation.Encrypted;
import io.ebean.annotation.Expose;
import io.ebean.annotation.Formula;
import io.ebean.annotation.HistoryExclude;
import io.ebean.annotation.Identity;
import io.ebean.annotation.Index;
import io.ebean.annotation.JsonIgnore;
import io.ebean.annotation.Length;
import io.ebean.annotation.SoftDelete;
import io.ebean.annotation.Sum;
import io.ebean.annotation.TenantId;
import io.ebean.annotation.UnmappedJson;
import io.ebean.annotation.UpdatedTimestamp;
@@ -40,6 +40,7 @@ import io.ebean.config.dbplatform.DbEncryptFunction;
import io.ebean.config.dbplatform.IdType;
import io.ebean.config.dbplatform.PlatformIdGenerator;
import io.ebeaninternal.server.deploy.DbMigrationInfo;
import io.ebeaninternal.server.deploy.IdentityMode;
import io.ebeaninternal.server.deploy.IndexDefinition;
import io.ebeaninternal.server.deploy.generatedproperty.GeneratedPropertyFactory;
import io.ebeaninternal.server.deploy.meta.DeployBeanProperty;
@@ -196,10 +197,8 @@ public class AnnotationFields extends AnnotationParser {
readJsonAnnotations(prop);
if (prop.getDbColumn() == null) {
// No @Column annotation or @Column.name() not set
// Use the NamingConvention to set the DB column name
String dbColumn = namingConvention.getColumnFromProperty(beanType, prop.getName());
prop.setDbColumn(dbColumn);
// No @Column or @Column.name() so use NamingConvention
prop.setDbColumn(namingConvention.getColumnFromProperty(beanType, prop.getName()));
}
Id id = get(prop, Id.class);
@@ -210,6 +209,10 @@ public class AnnotationFields extends AnnotationParser {
if (id != null) {
readIdScalar(prop);
}
Identity identity = get(prop, Identity.class);
if (identity != null) {
readIdentity(identity);
}
// determine the JDBC type using Lob/Temporal
// otherwise based on the property Class
@@ -381,6 +384,11 @@ public class AnnotationFields extends AnnotationParser {
}
}
private void readIdentity(Identity identity) {
final IdType idType = IdentityMode.idType(identity.type());
descriptor.setIdentityMode(new IdentityMode(idType, identity.generated(), identity.start(), identity.increment(), identity.sequenceName()));
}
private void readDbMigration(DeployBeanProperty prop) {
DbDefault dbDefault = get(prop, DbDefault.class);
if (dbDefault != null) {
@@ -521,34 +529,32 @@ public class AnnotationFields extends AnnotationParser {
}
}
descriptor.setIdGeneratedValue();
String genName = gen.generator();
SequenceGenerator sequenceGenerator = find(prop, SequenceGenerator.class);
if (sequenceGenerator != null) {
if (sequenceGenerator.name().equals(genName)) {
genName = sequenceGenerator.sequenceName();
SequenceGenerator seq = find(prop, SequenceGenerator.class);
if (seq != null) {
String seqName = seq.sequenceName();
if (seqName.isEmpty()) {
seqName = namingConvention.getSequenceName(descriptor.getBaseTable(), prop.getDbColumn());
}
descriptor.setSequenceInitialValue(sequenceGenerator.initialValue());
descriptor.setSequenceAllocationSize(sequenceGenerator.allocationSize());
descriptor.setIdentitySequence(seq.initialValue(), seq.allocationSize(), seqName);
}
GenerationType strategy = gen.strategy();
if (strategy == GenerationType.IDENTITY) {
descriptor.setIdType(IdType.IDENTITY);
descriptor.setIdentityType(IdType.IDENTITY);
} else if (strategy == GenerationType.SEQUENCE) {
descriptor.setIdType(IdType.SEQUENCE);
if (!genName.isEmpty()) {
descriptor.setIdGeneratorName(genName);
descriptor.setIdentityType(IdType.SEQUENCE);
if (!gen.generator().isEmpty()) {
descriptor.setIdentitySequenceGenerator(gen.generator());
}
} else if (strategy == GenerationType.AUTO) {
if (!genName.isEmpty()) {
if (!gen.generator().isEmpty()) {
// use a custom IdGenerator
PlatformIdGenerator idGenerator = generatedPropFactory.getIdGenerator(genName);
PlatformIdGenerator idGenerator = generatedPropFactory.getIdGenerator(gen.generator());
if (idGenerator == null) {
throw new IllegalStateException("No custom IdGenerator registered with name " + genName);
throw new IllegalStateException("No custom IdGenerator registered with name " + gen.generator());
}
descriptor.setCustomIdGenerator(idGenerator);
} else if (prop.getPropertyType().equals(UUID.class)) {
@@ -67,10 +67,8 @@ public abstract class AnnotationParser extends AnnotationBase {
prop.setImportedPrimaryKey();
} else {
prop.setId();
if (prop.getPropertyType().equals(UUID.class)) {
if (readConfig.isIdGeneratorAutomatic() && descriptor.getIdGeneratorName() == null) {
descriptor.setUuidGenerator();
}
if (prop.getPropertyType().equals(UUID.class) && readConfig.isIdGeneratorAutomatic()) {
descriptor.setUuidGenerator();
}
}
}