/** * 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 String generateAnnColumnAnnotation(Property property) { StringBuffer annotations = new StringBuffer(" "); boolean insertable = property.isInsertable(); boolean updatable = property.isUpdateable(); if (property.isComposite()) { annotations.append("@" + importType("javax.persistence.AttributeOverrides") + "( {"); Component component = (Component) property.getValue(); Iterator<?> subElements = component.getPropertyIterator(); buildRecursiveAttributeOverride(subElements, null, property, annotations); annotations.setLength(annotations.length() - 2); annotations.append(" } )"); } else { if (property.getColumnSpan() == 1) { Selectable selectable = (Selectable) property.getColumnIterator().next(); buildColumnAnnotation(selectable, annotations, insertable, updatable); } else { Iterator<?> columns = property.getColumnIterator(); annotations .append("@") .append(importType("org.hibernate.annotations.Columns")) .append("( { "); while (columns.hasNext()) { Selectable selectable = (Selectable) columns.next(); if (selectable.isFormula()) { // TODO formula in multicolumns not supported by annotations // annotations.append("/* TODO formula in multicolumns not supported by annotations // */"); } else { annotations.append("\n "); buildColumnAnnotation(selectable, annotations, insertable, updatable); annotations.append(", "); } } annotations.setLength(annotations.length() - 2); annotations.append(" } )"); } } return annotations.toString(); }
public GenerationStrategyPair buildPair() { if (hadInMemoryGeneration && hadInDatabaseGeneration) { throw new ValueGenerationStrategyException( "Composite attribute [" + mappingProperty.getName() + "] contained both in-memory" + " and in-database value generation"); } else if (hadInMemoryGeneration) { throw new NotYetImplementedException( "Still need to wire in composite in-memory value generation"); } else if (hadInDatabaseGeneration) { final Component composite = (Component) mappingProperty.getValue(); // we need the numbers to match up so we can properly handle 'referenced sql column values' if (inDatabaseStrategies.size() != composite.getPropertySpan()) { throw new ValueGenerationStrategyException( "Internal error : mismatch between number of collected in-db generation strategies" + " and number of attributes for composite attribute : " + mappingProperty.getName()); } // the base-line values for the aggregated InDatabaseValueGenerationStrategy we will build // here. GenerationTiming timing = GenerationTiming.INSERT; boolean referenceColumns = false; String[] columnValues = new String[composite.getColumnSpan()]; // start building the aggregate values int propertyIndex = -1; int columnIndex = 0; Iterator subProperties = composite.getPropertyIterator(); while (subProperties.hasNext()) { propertyIndex++; final Property subProperty = (Property) subProperties.next(); final InDatabaseValueGenerationStrategy subStrategy = inDatabaseStrategies.get(propertyIndex); if (subStrategy.getGenerationTiming() == GenerationTiming.ALWAYS) { // override the base-line to the more often "ALWAYS"... timing = GenerationTiming.ALWAYS; } if (subStrategy.referenceColumnsInSql()) { // override base-line value referenceColumns = true; } if (subStrategy.getReferencedColumnValues() != null) { if (subStrategy.getReferencedColumnValues().length != subProperty.getColumnSpan()) { throw new ValueGenerationStrategyException( "Internal error : mismatch between number of collected 'referenced column values'" + " and number of columns for composite attribute : " + mappingProperty.getName() + '.' + subProperty.getName()); } System.arraycopy( subStrategy.getReferencedColumnValues(), 0, columnValues, columnIndex, subProperty.getColumnSpan()); } } // then use the aggregated values to build the InDatabaseValueGenerationStrategy return new GenerationStrategyPair( new InDatabaseValueGenerationStrategyImpl(timing, referenceColumns, columnValues)); } else { return NO_GEN_PAIR; } }
@SuppressWarnings({CompilerWarnings.UNCHECKED}) private void buildEntityMetadatas() throws Exception { SessionFactoryImpl sessionFactory = ((SessionFactoryImpl) this.entityManagerFactory.getSessionFactory()); Class<?> entityBindingMappedClass; Class<? extends SdcctEntity> entityMappedClass; String entityName, entityPropName, entityPropFieldName; EntityMetadata entityMetadata; Map<String, PropertyMetadata> entityPropMetadatas; IndexedTypeDescriptor indexedEntityDesc; Method entityPropGetterMethod; boolean entityIndexed, entityPropIndexed; PropertyDescriptor indexedEntityPropDesc; PropertyMetadata entityPropMetadata; BidiMap<Integer, String> entityPropOrder; String[] entityPropOrderNames; for (PersistentClass entityBinding : metadata.getEntityBindings()) { if (((entityBindingMappedClass = entityBinding.getMappedClass()) == null) || !SdcctEntity.class.isAssignableFrom(entityBindingMappedClass)) { continue; } entityPropMetadatas = (entityMetadata = new EntityMetadataImpl( (entityName = entityBinding.getEntityName()), (entityIndexed = (indexedEntityDesc = searchIntegrator.getIndexedTypeDescriptor( (entityMappedClass = ((Class<? extends SdcctEntity>) entityBindingMappedClass)))) .isIndexed()), entityMappedClass, entityBinding.getTable().getName())) .getProperties(); this.entityMetadatas.put( ((Class<? extends SdcctEntity>) entityMappedClass.getInterfaces()[0]), entityMetadata); for (Property entityProp : IteratorUtils.asIterable( IteratorUtils.chainedIterator( ((Iterator<Property>) entityBinding.getRootClass().getPropertyIterator()), ((Iterator<Property>) entityBinding.getPropertyIterator())))) { entityPropName = entityProp.getName(); entityPropGetterMethod = entityProp.getGetter(entityMappedClass).getMethod(); if (entityProp.getColumnSpan() == 0) { continue; } entityPropIndexed = (entityIndexed && entityPropGetterMethod.isAnnotationPresent(Fields.class) && ((indexedEntityPropDesc = indexedEntityDesc.getProperty(entityPropName)) != null) && !indexedEntityPropDesc.isId()); entityPropMetadatas.put( entityPropName, (entityPropMetadata = new PropertyMetadataImpl( entityPropName, entityPropIndexed, ((Column) entityProp.getColumnIterator().next()).getName(), entityProp.getType()))); if (entityPropIndexed) { for (Field entityPropFieldAnno : entityPropGetterMethod.getAnnotation(Fields.class).value()) { if (entityPropFieldAnno.analyze() == Analyze.NO) { continue; } entityPropFieldName = entityPropFieldAnno.name(); switch (entityPropFieldAnno.analyzer().definition()) { case DbAnalyzerNames.EDGE_NGRAM: entityPropMetadata.setEdgeNgramFieldName(entityPropFieldName); break; case DbAnalyzerNames.LOWERCASE: entityPropMetadata.setLowercaseFieldName(entityPropFieldName); break; case DbAnalyzerNames.NGRAM: entityPropMetadata.setNgramFieldName(entityPropFieldName); break; case DbAnalyzerNames.PHONETIC: entityPropMetadata.setPhoneticFieldName(entityPropFieldName); break; } } } } entityMetadata.setIdProperty( entityPropMetadatas.get(entityBinding.getIdentifierProperty().getName())); entityPropOrder = entityMetadata.getPropertyOrder(); entityPropOrderNames = sessionFactory.getEntityPersister(entityName).getPropertyNames(); for (int a = 0; a < entityPropOrderNames.length; a++) { entityPropOrder.put(a, entityPropOrderNames[a]); } } LOGGER.debug( String.format( "Processed metadata for %d entities: [%s]", this.entityMetadatas.size(), this.entityMetadatas .values() .stream() .map(NamedBean::getName) .collect(Collectors.joining(", ")))); }