private void readColumn(Column columnAnn, DeployBeanProperty prop) { if (!isEmpty(columnAnn.name())) { String dbColumn = databasePlatform.convertQuotedIdentifiers(columnAnn.name()); prop.setDbColumn(dbColumn); } prop.setDbInsertable(columnAnn.insertable()); prop.setDbUpdateable(columnAnn.updatable()); prop.setNullable(columnAnn.nullable()); prop.setUnique(columnAnn.unique()); if (columnAnn.precision() > 0) { prop.setDbLength(columnAnn.precision()); } else if (columnAnn.length() != 255) { // set default 255 on DbTypeMap prop.setDbLength(columnAnn.length()); } prop.setDbScale(columnAnn.scale()); prop.setDbColumnDefn(columnAnn.columnDefinition()); String baseTable = descriptor.getBaseTable(); String tableName = columnAnn.table(); if (tableName.equals("") || tableName.equalsIgnoreCase(baseTable)) { // its a base table property... } else { // its on a secondary table... prop.setSecondaryTable(tableName); // DeployTableJoin tableJoin = info.getTableJoin(tableName); // tableJoin.addProperty(prop); } }
private void readId(Id id, DeployBeanProperty prop) { prop.setId(true); prop.setNullable(false); if (prop.getPropertyType().equals(UUID.class)) { // An Id of type UUID if (descriptor.getIdGeneratorName() == null) { // Without a generator explicitly specified // so will use the default one AUTO_UUID descriptor.setIdGeneratorName(UuidIdGenerator.AUTO_UUID); descriptor.setIdType(IdType.GENERATOR); } } }
private void readTemporal(Temporal temporal, DeployBeanProperty prop) { TemporalType type = temporal.value(); if (type.equals(TemporalType.DATE)) { prop.setDbType(Types.DATE); } else if (type.equals(TemporalType.TIMESTAMP)) { prop.setDbType(Types.TIMESTAMP); } else if (type.equals(TemporalType.TIME)) { prop.setDbType(Types.TIME); } else { throw new PersistenceException("Unhandled type " + type); } }
private void readGenValue(GeneratedValue gen, DeployBeanProperty prop) { String genName = gen.generator(); SequenceGenerator sequenceGenerator = find(prop, SequenceGenerator.class); if (sequenceGenerator != null) { if (sequenceGenerator.name().equals(genName)) { genName = sequenceGenerator.sequenceName(); } } GenerationType strategy = gen.strategy(); if (strategy == GenerationType.IDENTITY) { descriptor.setIdType(IdType.IDENTITY); } else if (strategy == GenerationType.SEQUENCE) { descriptor.setIdType(IdType.SEQUENCE); if (genName != null && genName.length() > 0) { descriptor.setIdGeneratorName(genName); } } else if (strategy == GenerationType.AUTO) { if (prop.getPropertyType().equals(UUID.class)) { descriptor.setIdGeneratorName(UuidIdGenerator.AUTO_UUID); descriptor.setIdType(IdType.GENERATOR); } else { // use DatabasePlatform defaults } } }
private DataEncryptSupport createDataEncryptSupport(DeployBeanProperty prop) { String table = info.getDescriptor().getBaseTable(); String column = prop.getDbColumn(); return util.createDataEncryptSupport(table, column); }
private DeployBeanProperty createProp( int level, DeployBeanDescriptor<?> desc, Field field, Class<?> beanType, Method getter, Method setter) { DeployBeanProperty prop = createProp(desc, field); if (prop == null) { // transient annotation on unsupported type return null; } else { prop.setOwningType(beanType); prop.setName(field.getName()); // the getter or setter could be null if we are using // javaagent type enhancement. If we are using subclass // generation then we do need to find the getter and setter prop.setReadMethod(getter); prop.setWriteMethod(setter); prop.setField(field); return prop; } }
private void setEncryption(DeployBeanProperty prop, boolean dbEncString, int dbLen) { util.checkEncryptKeyManagerDefined(prop.getFullBeanName()); ScalarType<?> st = prop.getScalarType(); if (byte[].class.equals(st.getType())) { // Always using Java client encryption rather than DB for encryption // of binary data (partially as this is not supported on all db's etc) // This could be reviewed at a later stage. ScalarTypeBytesBase baseType = (ScalarTypeBytesBase) st; DataEncryptSupport support = createDataEncryptSupport(prop); ScalarTypeBytesEncrypted encryptedScalarType = new ScalarTypeBytesEncrypted(baseType, support); prop.setScalarType(encryptedScalarType); prop.setLocalEncrypted(true); return; } if (dbEncString) { DbEncrypt dbEncrypt = util.getDbPlatform().getDbEncrypt(); if (dbEncrypt != null) { // check if we have a DB encryption function for this type int jdbcType = prop.getScalarType().getJdbcType(); DbEncryptFunction dbEncryptFunction = dbEncrypt.getDbEncryptFunction(jdbcType); if (dbEncryptFunction != null) { // Use DB functions to encrypt and decrypt prop.setDbEncryptFunction(dbEncryptFunction, dbEncrypt, dbLen); return; } } } prop.setScalarType(createScalarType(prop, st)); prop.setLocalEncrypted(true); if (dbLen > 0) { prop.setDbLength(dbLen); } }
/** Read the Id marker annotations on EmbeddedId properties. */ private void readAssocOne(DeployBeanProperty prop) { Id id = get(prop, Id.class); if (id != null) { prop.setId(true); prop.setNullable(false); } EmbeddedId embeddedId = get(prop, EmbeddedId.class); if (embeddedId != null) { prop.setId(true); prop.setNullable(false); prop.setEmbedded(true); } if (prop instanceof DeployBeanPropertyAssocOne<?>) { if (prop.isId() && !prop.isEmbedded()) { prop.setEmbedded(true); } readEmbeddedAttributeOverrides((DeployBeanPropertyAssocOne<?>) prop); } }
/** Create the appropriate properties for a bean. */ public void createProperties(DeployBeanDescriptor<?> desc) { createProperties(desc, desc.getBeanType(), 0); desc.sortProperties(); // check the transient properties... Iterator<DeployBeanProperty> it = desc.propertiesAll(); while (it.hasNext()) { DeployBeanProperty prop = it.next(); if (prop.isTransient()) { if (prop.getWriteMethod() == null || prop.getReadMethod() == null) { // Typically a helper method ... this is expected logger.finest("... transient: " + prop.getFullBeanName()); } else { // dubious, possible error... String msg = Message.msg("deploy.property.nofield", desc.getFullName(), prop.getName()); logger.warning(msg); } } } }
private void readField(DeployBeanProperty prop) { // all Enums will have a ScalarType assigned... boolean isEnum = prop.getPropertyType().isEnum(); Enumerated enumerated = get(prop, Enumerated.class); if (isEnum || enumerated != null) { util.setEnumScalarType(enumerated, prop); } // its persistent and assumed to be on the base table // rather than on a secondary table prop.setDbRead(true); prop.setDbInsertable(true); prop.setDbUpdateable(true); Column column = get(prop, Column.class); if (column != null) { readColumn(column, prop); } Expose expose = get(prop, Expose.class); if (expose != null) { prop.setExposeSerialize(expose.serialize()); prop.setExposeDeserialize(expose.deserialize()); } 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); } GeneratedValue gen = get(prop, GeneratedValue.class); if (gen != null) { readGenValue(gen, prop); } Id id = (Id) get(prop, Id.class); if (id != null) { readId(id, prop); } // determine the JDBC type using Lob/Temporal // otherwise based on the property Class Lob lob = get(prop, Lob.class); Temporal temporal = get(prop, Temporal.class); if (temporal != null) { readTemporal(temporal, prop); } else if (lob != null) { util.setLobType(prop); } Formula formula = get(prop, Formula.class); if (formula != null) { prop.setSqlFormula(formula.select(), formula.join()); } Version version = get(prop, Version.class); if (version != null) { // explicitly specify a version column prop.setVersionColumn(true); generatedPropFactory.setVersion(prop); } Basic basic = get(prop, Basic.class); if (basic != null) { prop.setFetchType(basic.fetch()); if (!basic.optional()) { prop.setNullable(false); } } else if (prop.isLob()) { // use the default Lob fetchType prop.setFetchType(defaultLobFetchType); } CreatedTimestamp ct = get(prop, CreatedTimestamp.class); if (ct != null) { generatedPropFactory.setInsertTimestamp(prop); } UpdatedTimestamp ut = get(prop, UpdatedTimestamp.class); if (ut != null) { generatedPropFactory.setUpdateTimestamp(prop); } if (validationAnnotations) { NotNull notNull = get(prop, NotNull.class); if (notNull != null && isNotNullOnAllValidationGroups(notNull.groups())) { // Not null on all validation groups so enable // DDL generation of Not Null Constraint prop.setNullable(false); } Size size = get(prop, Size.class); if (size != null) { if (size.max() < Integer.MAX_VALUE) { // explicitly specify a version column prop.setDbLength(size.max()); } } } EmbeddedColumns columns = get(prop, EmbeddedColumns.class); if (columns != null) { if (prop instanceof DeployBeanPropertyCompound) { DeployBeanPropertyCompound p = (DeployBeanPropertyCompound) prop; // convert into a Map String propColumns = columns.columns(); Map<String, String> propMap = StringHelper.delimitedToMap(propColumns, ",", "="); p.getDeployEmbedded().putAll(propMap); CtCompoundType<?> compoundType = p.getCompoundType(); if (compoundType == null) { throw new RuntimeException("No registered CtCompoundType for " + p.getPropertyType()); } } else { throw new RuntimeException( "Can't use EmbeddedColumns on ScalarType " + prop.getFullBeanName()); } } // Want to process last so we can use with @Formula Transient t = get(prop, Transient.class); if (t != null) { // it is not a persistent property. prop.setDbRead(false); prop.setDbInsertable(false); prop.setDbUpdateable(false); prop.setTransient(true); } if (!prop.isTransient()) { EncryptDeploy encryptDeploy = util.getEncryptDeploy(info.getDescriptor().getBaseTableFull(), prop.getDbColumn()); if (encryptDeploy == null || encryptDeploy.getMode().equals(Mode.MODE_ANNOTATION)) { Encrypted encrypted = get(prop, Encrypted.class); if (encrypted != null) { setEncryption(prop, encrypted.dbEncryption(), encrypted.dbLength()); } } else if (Mode.MODE_ENCRYPT.equals(encryptDeploy.getMode())) { setEncryption(prop, encryptDeploy.isDbEncrypt(), encryptDeploy.getDbLength()); } } Index index = get(prop, Index.class); if (index != null) { if (hasRelationshipItem(prop)) { throw new RuntimeException("Can't use Index on foreign key relationships."); } prop.setIndexed(true); prop.setIndexName(index.value()); } }
private ScalarTypeBytesBase getDbEncryptType(DeployBeanProperty prop) { int dbType = prop.isLob() ? Types.BLOB : Types.VARBINARY; return (ScalarTypeBytesBase) util.getTypeManager().getScalarType(dbType); }
@SuppressWarnings({"unchecked", "rawtypes"}) public DeployBeanPropertyLists( BeanDescriptorMap owner, BeanDescriptor<?> desc, DeployBeanDescriptor<?> deploy) { this.desc = desc; setImportedPrimaryKeys(deploy); DeployBeanPropertyAssocOne<?> deployUnidirectional = deploy.getUnidirectional(); if (deployUnidirectional == null) { unidirectional = null; } else { unidirectional = new BeanPropertyAssocOne(owner, desc, deployUnidirectional); } this.propertyMap = new LinkedHashMap<String, BeanProperty>(); // see if there is a discriminator property we should add String discriminatorColumn = null; BeanProperty discProperty = null; InheritInfo inheritInfo = deploy.getInheritInfo(); if (inheritInfo != null) { // Create a BeanProperty for the discriminator column to support // using RawSql queries with inheritance discriminatorColumn = inheritInfo.getDiscriminatorColumn(); DeployBeanProperty discDeployProp = new DeployBeanProperty(deploy, String.class, new ScalarTypeString(), null); discDeployProp.setDiscriminator(); discDeployProp.setName(discriminatorColumn); discDeployProp.setDbColumn(discriminatorColumn); // only register it in the propertyMap. This might not be used if // an explicit property is mapped to the discriminator on the bean discProperty = new BeanProperty(desc, discDeployProp); } for (DeployBeanProperty prop : deploy.propertiesAll()) { if (discriminatorColumn != null && discriminatorColumn.equals(prop.getDbColumn())) { // we have an explicit property mapped to the discriminator column prop.setDiscriminator(); discProperty = null; } BeanProperty beanProp = createBeanProperty(owner, prop); propertyMap.put(beanProp.getName(), beanProp); } int order = 0; for (BeanProperty prop : propertyMap.values()) { prop.setDeployOrder(order++); allocateToList(prop); } if (discProperty != null) { // put the discriminator property into the property map only // (after the real properties have been organised into their lists) propertyMap.put(discProperty.getName(), discProperty); } List<DeployTableJoin> deployTableJoins = deploy.getTableJoins(); tableJoins = new TableJoin[deployTableJoins.size()]; for (int i = 0; i < deployTableJoins.size(); i++) { tableJoins[i] = new TableJoin(deployTableJoins.get(i)); } }
/** * reflect the bean properties from Class. Some of these properties may not map to database * columns. */ private void createProperties(DeployBeanDescriptor<?> desc, Class<?> beanType, int level) { boolean scalaObject = desc.isScalaObject(); try { Method[] declaredMethods = beanType.getDeclaredMethods(); Field[] fields = beanType.getDeclaredFields(); for (int i = 0; i < fields.length; i++) { Field field = fields[i]; if (Modifier.isStatic(field.getModifiers())) { // not interested in static fields } else if (Modifier.isTransient(field.getModifiers())) { // not interested in transient fields logger.finer("Skipping transient field " + field.getName() + " in " + beanType.getName()); } else if (ignoreFieldByName(field.getName())) { // not interested this field (ebean or aspectJ field) } else { String fieldName = getFieldName(field, beanType); String initFieldName = initCap(fieldName); Method getter = findGetter(field, initFieldName, declaredMethods, scalaObject); Method setter = findSetter(field, initFieldName, declaredMethods, scalaObject); DeployBeanProperty prop = createProp(level, desc, field, beanType, getter, setter); if (prop == null) { // transient annotation on unsupported type } else { // set a order that gives priority to inherited properties // push Id/EmbeddedId up and CreatedTimestamp/UpdatedTimestamp down int sortOverride = prop.getSortOverride(); prop.setSortOrder((level * 10000 + 100 - i + sortOverride)); DeployBeanProperty replaced = desc.addBeanProperty(prop); if (replaced != null) { if (replaced.isTransient()) { // expected for inheritance... } else { String msg = "Huh??? property " + prop.getFullBeanName() + " being defined twice"; msg += " but replaced property was not transient? This is not expected?"; logger.warning(msg); } } } } } Class<?> superClass = beanType.getSuperclass(); if (!superClass.equals(Object.class)) { // recursively add any properties in the inheritance heirarchy // up to the Object.class level... createProperties(desc, superClass, level + 1); } } catch (PersistenceException ex) { throw ex; } catch (Exception ex) { throw new PersistenceException(ex); } }
public BeanProperty(BeanDescriptor<?> descriptor, DeployBeanProperty deploy) { this.descriptor = descriptor; this.name = InternString.intern(deploy.getName()); this.propertyIndex = deploy.getPropertyIndex(); this.unidirectionalShadow = deploy.isUndirectionalShadow(); this.discriminator = deploy.isDiscriminator(); this.localEncrypted = deploy.isLocalEncrypted(); this.dbEncrypted = deploy.isDbEncrypted(); this.dbEncryptedType = deploy.getDbEncryptedType(); this.dbEncryptFunction = deploy.getDbEncryptFunction(); this.dbBind = deploy.getDbBind(); this.dbRead = deploy.isDbRead(); this.dbInsertable = deploy.isDbInsertable(); this.dbUpdatable = deploy.isDbUpdateable(); this.excludedFromHistory = deploy.isExcludedFromHistory(); this.draft = deploy.isDraft(); this.draftDirty = deploy.isDraftDirty(); this.draftOnly = deploy.isDraftOnly(); this.draftReset = deploy.isDraftReset(); this.secondaryTable = deploy.isSecondaryTable(); if (secondaryTable) { this.secondaryTableJoin = new TableJoin(deploy.getSecondaryTableJoin()); this.secondaryTableJoinPrefix = deploy.getSecondaryTableJoinPrefix(); } else { this.secondaryTableJoin = null; this.secondaryTableJoinPrefix = null; } this.fetchEager = deploy.isFetchEager(); this.isTransient = deploy.isTransient(); this.nullable = deploy.isNullable(); this.unique = deploy.isUnique(); this.naturalKey = deploy.isNaturalKey(); this.dbLength = deploy.getDbLength(); this.dbScale = deploy.getDbScale(); this.dbColumnDefn = InternString.intern(deploy.getDbColumnDefn()); this.dbColumnDefault = deploy.getDbColumnDefault(); this.inherited = false; // deploy.isInherited(); this.owningType = deploy.getOwningType(); this.local = deploy.isLocal(); this.version = deploy.isVersionColumn(); this.embedded = deploy.isEmbedded(); this.id = deploy.isId(); this.generatedProperty = deploy.getGeneratedProperty(); this.getter = deploy.getGetter(); this.setter = deploy.getSetter(); this.dbColumn = tableAliasIntern(descriptor, deploy.getDbColumn(), false, null); this.dbComment = deploy.getDbComment(); this.sqlFormulaJoin = InternString.intern(deploy.getSqlFormulaJoin()); this.sqlFormulaSelect = InternString.intern(deploy.getSqlFormulaSelect()); this.formula = sqlFormulaSelect != null; this.dbType = deploy.getDbType(); this.scalarType = deploy.getScalarType(); this.lob = isLobType(dbType); this.propertyType = deploy.getPropertyType(); this.field = deploy.getField(); this.docOptions = deploy.getDocPropertyOptions(); this.elPlaceHolder = tableAliasIntern(descriptor, deploy.getElPlaceHolder(), false, null); this.elPlaceHolderEncrypted = tableAliasIntern(descriptor, deploy.getElPlaceHolder(), dbEncrypted, dbColumn); this.softDelete = deploy.isSoftDelete(); if (softDelete) { ScalarTypeBoolean.BooleanBase boolType = (ScalarTypeBoolean.BooleanBase) scalarType; this.softDeleteDbSet = dbColumn + "=" + boolType.getDbTrueLiteral(); this.softDeleteDbPredicate = "." + dbColumn + "," + boolType.getDbFalseLiteral() + ")=" + boolType.getDbFalseLiteral(); } else { this.softDeleteDbSet = null; this.softDeleteDbPredicate = null; } this.jsonSerialize = deploy.isJsonSerialize(); this.jsonDeserialize = deploy.isJsonDeserialize(); }
/** Creates place holder objects that should never be called. */ public static BeanReflectSetter create(DeployBeanProperty prop) { String fullName = prop.getFullBeanName(); Method writeMethod = prop.getWriteMethod(); return new RefCalled(fullName, writeMethod); }