private SimpleValue bindColumnToSimpleValue( Table table, Column column, Mapping mapping, boolean generatedIdentifier) { SimpleValue value = new SimpleValue(table); value.addColumn(column); value.setTypeName(guessAndAlignType(table, column, mapping, generatedIdentifier)); return value; }
public void copyTypeFrom(SimpleValue sourceValue) { setTypeName(sourceValue.getTypeName()); setTypeParameters(sourceValue.getTypeParameters()); type = sourceValue.type; attributeConverterDefinition = sourceValue.attributeConverterDefinition; }
@Override protected void addColumnBinding(SimpleValue value) { if (StringHelper.isEmpty(mappedBy)) { // was the column explicitly quoted in the mapping/annotation // TODO: in metamodel, we need to better split global quoting and explicit quoting w/ respect // to logical names boolean isLogicalColumnQuoted = StringHelper.isQuoted(getLogicalColumnName()); final ObjectNameNormalizer nameNormalizer = getBuildingContext().getObjectNameNormalizer(); final String logicalColumnName = nameNormalizer.normalizeIdentifierQuotingAsString(getLogicalColumnName()); final String referencedColumn = nameNormalizer.normalizeIdentifierQuotingAsString(getReferencedColumn()); final String unquotedLogColName = StringHelper.unquote(logicalColumnName); final String unquotedRefColumn = StringHelper.unquote(referencedColumn); String logicalCollectionColumnName = StringHelper.isNotEmpty(unquotedLogColName) ? unquotedLogColName : getPropertyName() + '_' + unquotedRefColumn; logicalCollectionColumnName = getBuildingContext() .getMetadataCollector() .getDatabase() .getJdbcEnvironment() .getIdentifierHelper() .toIdentifier(logicalCollectionColumnName, isLogicalColumnQuoted) .render(); getBuildingContext() .getMetadataCollector() .addColumnNameBinding(value.getTable(), logicalCollectionColumnName, getMappingColumn()); } }
private void updatePrimaryKey(RootClass rc, PrimaryKeyInfo pki) { SimpleValue idValue = (SimpleValue) rc.getIdentifierProperty().getValue(); Properties defaultStrategyProperties = new Properties(); Property constrainedOneToOne = getConstrainedOneToOne(rc); if (constrainedOneToOne != null) { if (pki.suggestedStrategy == null) { idValue.setIdentifierGeneratorStrategy("foreign"); } if (pki.suggestedProperties == null) { defaultStrategyProperties.setProperty("property", constrainedOneToOne.getName()); idValue.setIdentifierGeneratorProperties(defaultStrategyProperties); } } }
/** * Tests that single- and multi-column user type mappings work correctly. Also Checks that the * "sqlType" property is honoured. */ public void testUserTypeMappings() { DefaultGrailsDomainConfiguration config = getDomainConfig(MULTI_COLUMN_USER_TYPE_DEFINITION); PersistentClass persistentClass = config.getClassMapping("Item"); // First check the "name" property and its associated column. Property nameProperty = persistentClass.getProperty("name"); assertEquals(1, nameProperty.getColumnSpan()); assertEquals("name", nameProperty.getName()); Column column = (Column) nameProperty.getColumnIterator().next(); assertEquals("s_name", column.getName()); assertEquals("text", column.getSqlType()); // Next the "other" property. Property otherProperty = persistentClass.getProperty("other"); assertEquals(1, otherProperty.getColumnSpan()); assertEquals("other", otherProperty.getName()); column = (Column) otherProperty.getColumnIterator().next(); assertEquals("other", column.getName()); assertEquals("wrapper-characters", column.getSqlType()); assertEquals(MyUserType.class.getName(), column.getValue().getType().getName()); assertTrue(column.getValue() instanceof SimpleValue); SimpleValue v = (SimpleValue) column.getValue(); assertEquals("myParam1", v.getTypeParameters().get("param1")); assertEquals("myParam2", v.getTypeParameters().get("param2")); // And now for the "price" property, which should have two // columns. Property priceProperty = persistentClass.getProperty("price"); assertEquals(2, priceProperty.getColumnSpan()); assertEquals("price", priceProperty.getName()); Iterator<?> colIter = priceProperty.getColumnIterator(); column = (Column) colIter.next(); assertEquals("value", column.getName()); assertNull("SQL type should have been 'null' for 'value' column.", column.getSqlType()); column = (Column) colIter.next(); assertEquals("currency_code", column.getName()); assertEquals("text", column.getSqlType()); }
public void /*test*/ AddNewProperty() { System.out.println("******************* testAddNewProperty ********************"); PersistentClass userMapping = HibernateUtil.getClassMapping(User.class); Column column = new Column(); column.setName("MOTTO"); column.setNullable(false); column.setUnique(true); column.setSqlType("VARCHAR"); userMapping.getTable().addColumn(column); SimpleValue value = new SimpleValue(); value.setTable(userMapping.getTable()); value.addColumn(column); value.setTypeName("string"); Property prop = new Property(); prop.setValue(value); prop.setName("motto"); prop.setPropertyAccessorName("field"); prop.setNodeName(prop.getName()); userMapping.addProperty(prop); HibernateUtil.rebuildSessionFactory(); ClassMetadata metadata = HibernateUtil.getClassMetadata(User.class); String[] propNames = metadata.getPropertyNames(); boolean mottoFound = false; for (int i = 0; i < propNames.length; i++) { String propName = propNames[i]; if (propName.equalsIgnoreCase("motto")) { mottoFound = true; break; } } assertTrue(mottoFound); }
/** * Builds the <code>Join</code> instance for the mapped by side of a <i>OneToOne</i> association * using a join tables. * * <p>Note:<br> * * <ul> * <li>From the mappedBy side we should not create the PK nor the FK, this is handled from the * other side. * <li>This method is a dirty dupe of EntityBinder.bindSecondaryTable</i>. */ private Join buildJoinFromMappedBySide( PersistentClass persistentClass, Property otherSideProperty, Join originalJoin) { Join join = new Join(); join.setPersistentClass(persistentClass); // no check constraints available on joins join.setTable(originalJoin.getTable()); join.setInverse(true); SimpleValue key = new DependantValue(mappings, join.getTable(), persistentClass.getIdentifier()); // TODO support @ForeignKey join.setKey(key); join.setSequentialSelect(false); // TODO support for inverse and optional join.setOptional(true); // perhaps not quite per-spec, but a Good Thing anyway key.setCascadeDeleteEnabled(false); Iterator mappedByColumns = otherSideProperty.getValue().getColumnIterator(); while (mappedByColumns.hasNext()) { Column column = (Column) mappedByColumns.next(); Column copy = new Column(); copy.setLength(column.getLength()); copy.setScale(column.getScale()); copy.setValue(key); copy.setName(column.getQuotedName()); copy.setNullable(column.isNullable()); copy.setPrecision(column.getPrecision()); copy.setUnique(column.isUnique()); copy.setSqlType(column.getSqlType()); copy.setCheckConstraint(column.getCheckConstraint()); copy.setComment(column.getComment()); copy.setDefaultValue(column.getDefaultValue()); key.addColumn(copy); } persistentClass.addJoin(join); return join; }
@SuppressWarnings({"unchecked"}) public void doSecondPass(Map persistentClasses) throws MappingException { PersistentClass referencedPersistentClass = (PersistentClass) persistentClasses.get(referencedEntityName); // TODO better error names if (referencedPersistentClass == null) { throw new AnnotationException("Unknown entity name: " + referencedEntityName); } if (!(referencedPersistentClass.getIdentifier() instanceof Component)) { throw new AssertionFailure( "Unexpected identifier type on the referenced entity when mapping a @MapsId: " + referencedEntityName); } Component referencedComponent = (Component) referencedPersistentClass.getIdentifier(); Iterator<Property> properties = referencedComponent.getPropertyIterator(); // prepare column name structure boolean isExplicitReference = true; Map<String, Ejb3JoinColumn> columnByReferencedName = new HashMap<String, Ejb3JoinColumn>(joinColumns.length); for (Ejb3JoinColumn joinColumn : joinColumns) { final String referencedColumnName = joinColumn.getReferencedColumn(); if (referencedColumnName == null || BinderHelper.isEmptyAnnotationValue(referencedColumnName)) { break; } // JPA 2 requires referencedColumnNames to be case insensitive columnByReferencedName.put(referencedColumnName.toLowerCase(), joinColumn); } // try default column orientation int index = 0; if (columnByReferencedName.isEmpty()) { isExplicitReference = false; for (Ejb3JoinColumn joinColumn : joinColumns) { columnByReferencedName.put("" + index, joinColumn); index++; } index = 0; } while (properties.hasNext()) { Property referencedProperty = properties.next(); if (referencedProperty.isComposite()) { throw new AssertionFailure( "Unexpected nested component on the referenced entity when mapping a @MapsId: " + referencedEntityName); } else { Property property = new Property(); property.setName(referencedProperty.getName()); property.setNodeName(referencedProperty.getNodeName()); // FIXME set optional? // property.setOptional( property.isOptional() ); property.setPersistentClass(component.getOwner()); property.setPropertyAccessorName(referencedProperty.getPropertyAccessorName()); SimpleValue value = new SimpleValue(mappings, component.getTable()); property.setValue(value); final SimpleValue referencedValue = (SimpleValue) referencedProperty.getValue(); value.setTypeName(referencedValue.getTypeName()); value.setTypeParameters(referencedValue.getTypeParameters()); final Iterator<Column> columns = referencedValue.getColumnIterator(); if (joinColumns[0].isNameDeferred()) { joinColumns[0].copyReferencedStructureAndCreateDefaultJoinColumns( referencedPersistentClass, columns, value); } else { // FIXME take care of Formula while (columns.hasNext()) { Column column = columns.next(); final Ejb3JoinColumn joinColumn; String logicalColumnName = null; if (isExplicitReference) { final String columnName = column.getName(); logicalColumnName = mappings.getLogicalColumnName(columnName, referencedPersistentClass.getTable()); // JPA 2 requires referencedColumnNames to be case insensitive joinColumn = columnByReferencedName.get(logicalColumnName.toLowerCase()); } else { joinColumn = columnByReferencedName.get("" + index); index++; } if (joinColumn == null && !joinColumns[0].isNameDeferred()) { throw new AnnotationException( isExplicitReference ? "Unable to find column reference in the @MapsId mapping: " + logicalColumnName : "Implicit column reference in the @MapsId mapping fails, try to use explicit referenceColumnNames: " + referencedEntityName); } final String columnName = joinColumn == null || joinColumn.isNameDeferred() ? "tata_" + column.getName() : joinColumn.getName(); value.addColumn(new Column(columnName)); column.setValue(value); } } component.addProperty(property); } } }
private PrimaryKeyInfo bindPrimaryKeyToProperties( Table table, RootClass rc, Set processed, Mapping mapping, DatabaseCollector collector) { SimpleValue id = null; String idPropertyname = null; PrimaryKeyInfo pki = new PrimaryKeyInfo(); List keyColumns = null; if (table.getPrimaryKey() != null) { keyColumns = table.getPrimaryKey().getColumns(); } else { log.debug("No primary key found for " + table + ", using all properties as the identifier."); keyColumns = new ArrayList(); Iterator iter = table.getColumnIterator(); while (iter.hasNext()) { Column col = (Column) iter.next(); keyColumns.add(col); } } final TableIdentifier tableIdentifier = TableIdentifier.create(table); String tableIdentifierStrategyName = "assigned"; boolean naturalId; if (keyColumns.size() > 1) { log.debug( "id strategy for " + rc.getEntityName() + " since it has a multiple column primary key"); naturalId = true; id = handleCompositeKey(rc, processed, keyColumns, mapping); idPropertyname = revengStrategy.tableToIdentifierPropertyName(tableIdentifier); if (idPropertyname == null) { idPropertyname = "id"; } } else { pki.suggestedStrategy = revengStrategy.getTableIdentifierStrategyName(tableIdentifier); String suggestedStrategy = pki.suggestedStrategy; if (suggestedStrategy == null) { suggestedStrategy = collector.getSuggestedIdentifierStrategy( tableIdentifier.getCatalog(), tableIdentifier.getSchema(), tableIdentifier.getName()); if (suggestedStrategy == null) { suggestedStrategy = "assigned"; } tableIdentifierStrategyName = suggestedStrategy; } else { tableIdentifierStrategyName = suggestedStrategy; } naturalId = "assigned".equals(tableIdentifierStrategyName); Column pkc = (Column) keyColumns.get(0); checkColumn(pkc); id = bindColumnToSimpleValue(table, pkc, mapping, !naturalId); idPropertyname = revengStrategy.tableToIdentifierPropertyName(tableIdentifier); if (idPropertyname == null) { idPropertyname = revengStrategy.columnToPropertyName(tableIdentifier, pkc.getName()); } processed.add(pkc); } id.setIdentifierGeneratorStrategy(tableIdentifierStrategyName); pki.suggestedProperties = revengStrategy.getTableIdentifierProperties(tableIdentifier); id.setIdentifierGeneratorProperties(pki.suggestedProperties); if (naturalId) { id.setNullValue("undefined"); } Property property = makeProperty( tableIdentifier, makeUnique(rc, idPropertyname), id, true, true, false, null, null); rc.setIdentifierProperty(property); rc.setIdentifier(id); return pki; }
/** * @param rc * @param processed * @param table * @param object */ private Property bindOneToMany( PersistentClass rc, ForeignKey foreignKey, Set processed, Mapping mapping) { Table collectionTable = foreignKey.getTable(); // Collection collection = new org.hibernate.mapping.Set(rc); // MASTER TODO: allow overriding // collection type Collection collection = new org.hibernate.mapping.List(rc); // MASTER TODO: allow overriding collection type collection.setCollectionTable(collectionTable); // CHILD+ boolean manyToMany = revengStrategy.isManyToManyTable(collectionTable); if (manyToMany) { // log.debug("Rev.eng said here is a many-to-many"); // TODO: handle "the other side should influence the name" } if (manyToMany) { ManyToOne element = new ManyToOne(collection.getCollectionTable()); // TODO: find the other foreignkey and choose the other side. Iterator foreignKeyIterator = foreignKey.getTable().getForeignKeyIterator(); List keys = new ArrayList(); while (foreignKeyIterator.hasNext()) { Object next = foreignKeyIterator.next(); if (next != foreignKey) { keys.add(next); } } if (keys.size() > 1) { throw new JDBCBinderException( "more than one other foreign key to choose from!"); // todo: handle better ? } ForeignKey fk = (ForeignKey) keys.get(0); String tableToClassName = bindCollection(rc, foreignKey, fk, collection); element.setReferencedEntityName(tableToClassName); element.addColumn(fk.getColumn(0)); collection.setElement(element); } else { String tableToClassName = bindCollection(rc, foreignKey, null, collection); OneToMany oneToMany = new OneToMany(collection.getOwner()); oneToMany.setReferencedEntityName(tableToClassName); // Child mappings.addSecondPass(new JDBCCollectionSecondPass(mappings, collection)); collection.setElement(oneToMany); } // bind keyvalue KeyValue referencedKeyValue; String propRef = collection.getReferencedPropertyName(); if (propRef == null) { referencedKeyValue = collection.getOwner().getIdentifier(); } else { referencedKeyValue = (KeyValue) collection.getOwner().getProperty(propRef).getValue(); } SimpleValue keyValue = new DependantValue(collectionTable, referencedKeyValue); // keyValue.setForeignKeyName("none"); // Avoid creating the foreignkey // key.setCascadeDeleteEnabled( "cascade".equals( subnode.attributeValue("on-delete") ) ); Iterator columnIterator = foreignKey.getColumnIterator(); while (columnIterator.hasNext()) { Column fkcolumn = (Column) columnIterator.next(); if (fkcolumn.getSqlTypeCode() != null) { // TODO: user defined foreign ref columns does not have a type set. guessAndAlignType( collectionTable, fkcolumn, mapping, false); // needed to ensure foreign key columns has same type as the "property" column. } keyValue.addColumn(fkcolumn); } collection.setKey(keyValue); mappings.addCollection(collection); return makeCollectionProperty( StringHelper.unqualify(collection.getRole()), true, rc.getTable(), foreignKey, collection, true); // return makeProperty(TableIdentifier.create( rc.getTable() ), StringHelper.unqualify( // collection.getRole() ), collection, true, true, true, "none", null); // TODO: cascade isn't // all by default }