use of org.hibernate.AnnotationException in project hibernate-orm by hibernate.
the class Ejb3Column method initMappingColumn.
protected void initMappingColumn(String columnName, String propertyName, int length, int precision, int scale, boolean nullable, String sqlType, boolean unique, boolean applyNamingStrategy) {
if (StringHelper.isNotEmpty(formulaString)) {
this.formula = new Formula();
this.formula.setFormula(formulaString);
} else {
this.mappingColumn = new Column();
redefineColumnName(columnName, propertyName, applyNamingStrategy);
this.mappingColumn.setLength(length);
if (precision > 0) {
// revelent precision
this.mappingColumn.setPrecision(precision);
this.mappingColumn.setScale(scale);
}
this.mappingColumn.setNullable(nullable);
this.mappingColumn.setSqlType(sqlType);
this.mappingColumn.setUnique(unique);
if (writeExpression != null && !writeExpression.matches("[^?]*\\?[^?]*")) {
throw new AnnotationException("@WriteExpression must contain exactly one value placeholder ('?') character: property [" + propertyName + "] and column [" + logicalColumnName + "]");
}
if (readExpression != null) {
this.mappingColumn.setCustomRead(readExpression);
}
if (writeExpression != null) {
this.mappingColumn.setCustomWrite(writeExpression);
}
}
}
use of org.hibernate.AnnotationException in project hibernate-orm by hibernate.
the class Ejb3JoinColumn method buildDefaultColumnName.
private String buildDefaultColumnName(final PersistentClass referencedEntity, final String logicalReferencedColumn) {
final Database database = getBuildingContext().getMetadataCollector().getDatabase();
final ImplicitNamingStrategy implicitNamingStrategy = getBuildingContext().getBuildingOptions().getImplicitNamingStrategy();
final PhysicalNamingStrategy physicalNamingStrategy = getBuildingContext().getBuildingOptions().getPhysicalNamingStrategy();
Identifier columnIdentifier;
boolean mappedBySide = mappedByTableName != null || mappedByPropertyName != null;
boolean ownerSide = getPropertyName() != null;
Boolean isRefColumnQuoted = StringHelper.isQuoted(logicalReferencedColumn);
final String unquotedLogicalReferenceColumn = isRefColumnQuoted ? StringHelper.unquote(logicalReferencedColumn) : logicalReferencedColumn;
if (mappedBySide) {
// NOTE : While it is completely misleading here to allow for the combination
// of a "JPA ElementCollection" to be mappedBy, the code that uses this
// class relies on this behavior for handling the inverse side of
// many-to-many mappings
final AttributePath attributePath = AttributePath.parse(mappedByPropertyName);
final ImplicitJoinColumnNameSource.Nature implicitNamingNature;
if (getPropertyHolder().isEntity()) {
implicitNamingNature = ImplicitJoinColumnNameSource.Nature.ENTITY;
} else if (JPA2ElementCollection) {
implicitNamingNature = ImplicitJoinColumnNameSource.Nature.ELEMENT_COLLECTION;
} else {
implicitNamingNature = ImplicitJoinColumnNameSource.Nature.ENTITY_COLLECTION;
}
columnIdentifier = implicitNamingStrategy.determineJoinColumnName(new ImplicitJoinColumnNameSource() {
private final EntityNaming entityNaming = new EntityNaming() {
@Override
public String getClassName() {
return referencedEntity.getClassName();
}
@Override
public String getEntityName() {
return referencedEntity.getEntityName();
}
@Override
public String getJpaEntityName() {
return referencedEntity.getJpaEntityName();
}
};
private final Identifier referencedTableName = getBuildingContext().getMetadataCollector().getDatabase().toIdentifier(mappedByTableName);
@Override
public Nature getNature() {
return implicitNamingNature;
}
@Override
public EntityNaming getEntityNaming() {
return entityNaming;
}
@Override
public AttributePath getAttributePath() {
return attributePath;
}
@Override
public Identifier getReferencedTableName() {
return referencedTableName;
}
@Override
public Identifier getReferencedColumnName() {
if (logicalReferencedColumn != null) {
return getBuildingContext().getMetadataCollector().getDatabase().toIdentifier(logicalReferencedColumn);
}
if (mappedByEntityName == null || mappedByPropertyName == null) {
return null;
}
final PersistentClass mappedByEntityBinding = getBuildingContext().getMetadataCollector().getEntityBinding(mappedByEntityName);
final Property mappedByProperty = mappedByEntityBinding.getProperty(mappedByPropertyName);
final SimpleValue value = (SimpleValue) mappedByProperty.getValue();
final Iterator<Selectable> selectableValues = value.getColumnIterator();
if (!selectableValues.hasNext()) {
throw new AnnotationException(String.format(Locale.ENGLISH, "mapped-by [%s] defined for attribute [%s] referenced an invalid property (no columns)", mappedByPropertyName, propertyHolder.getPath()));
}
final Selectable selectable = selectableValues.next();
if (!Column.class.isInstance(selectable)) {
throw new AnnotationException(String.format(Locale.ENGLISH, "mapped-by [%s] defined for attribute [%s] referenced an invalid property (formula)", mappedByPropertyName, propertyHolder.getPath()));
}
if (selectableValues.hasNext()) {
throw new AnnotationException(String.format(Locale.ENGLISH, "mapped-by [%s] defined for attribute [%s] referenced an invalid property (multiple columns)", mappedByPropertyName, propertyHolder.getPath()));
}
return getBuildingContext().getMetadataCollector().getDatabase().toIdentifier(((Column) selectable).getQuotedName());
}
@Override
public MetadataBuildingContext getBuildingContext() {
return Ejb3JoinColumn.this.getBuildingContext();
}
});
// one element was quoted so we quote
if (isRefColumnQuoted || StringHelper.isQuoted(mappedByTableName)) {
columnIdentifier = Identifier.quote(columnIdentifier);
}
} else if (ownerSide) {
final String logicalTableName = getBuildingContext().getMetadataCollector().getLogicalTableName(referencedEntity.getTable());
final ImplicitJoinColumnNameSource.Nature implicitNamingNature;
if (JPA2ElementCollection) {
implicitNamingNature = ImplicitJoinColumnNameSource.Nature.ELEMENT_COLLECTION;
} else if (getPropertyHolder().isEntity()) {
implicitNamingNature = ImplicitJoinColumnNameSource.Nature.ENTITY;
} else {
implicitNamingNature = ImplicitJoinColumnNameSource.Nature.ENTITY_COLLECTION;
}
columnIdentifier = getBuildingContext().getBuildingOptions().getImplicitNamingStrategy().determineJoinColumnName(new ImplicitJoinColumnNameSource() {
private final EntityNaming entityNaming = new EntityNaming() {
@Override
public String getClassName() {
return referencedEntity.getClassName();
}
@Override
public String getEntityName() {
return referencedEntity.getEntityName();
}
@Override
public String getJpaEntityName() {
return referencedEntity.getJpaEntityName();
}
};
private final AttributePath attributePath = AttributePath.parse(getPropertyName());
private final Identifier referencedTableName = getBuildingContext().getMetadataCollector().getDatabase().toIdentifier(logicalTableName);
private final Identifier referencedColumnName = getBuildingContext().getMetadataCollector().getDatabase().toIdentifier(logicalReferencedColumn);
@Override
public Nature getNature() {
return implicitNamingNature;
}
@Override
public EntityNaming getEntityNaming() {
return entityNaming;
}
@Override
public AttributePath getAttributePath() {
return attributePath;
}
@Override
public Identifier getReferencedTableName() {
return referencedTableName;
}
@Override
public Identifier getReferencedColumnName() {
return referencedColumnName;
}
@Override
public MetadataBuildingContext getBuildingContext() {
return Ejb3JoinColumn.this.getBuildingContext();
}
});
// HHH-11826 magic. See Ejb3Column and the HHH-6005 comments
if (columnIdentifier.getText().contains("_collection&&element_")) {
columnIdentifier = Identifier.toIdentifier(columnIdentifier.getText().replace("_collection&&element_", "_"), columnIdentifier.isQuoted());
}
// one element was quoted so we quote
if (isRefColumnQuoted || StringHelper.isQuoted(logicalTableName)) {
columnIdentifier = Identifier.quote(columnIdentifier);
}
} else {
final Identifier logicalTableName = database.toIdentifier(getBuildingContext().getMetadataCollector().getLogicalTableName(referencedEntity.getTable()));
// is an intra-entity hierarchy table join so copy the name by default
columnIdentifier = implicitNamingStrategy.determinePrimaryKeyJoinColumnName(new ImplicitPrimaryKeyJoinColumnNameSource() {
@Override
public MetadataBuildingContext getBuildingContext() {
return Ejb3JoinColumn.this.getBuildingContext();
}
@Override
public Identifier getReferencedTableName() {
return logicalTableName;
}
@Override
public Identifier getReferencedPrimaryKeyColumnName() {
return database.toIdentifier(logicalReferencedColumn);
}
});
if (!columnIdentifier.isQuoted() && (isRefColumnQuoted || logicalTableName.isQuoted())) {
columnIdentifier = Identifier.quote(columnIdentifier);
}
}
return physicalNamingStrategy.toPhysicalColumnName(columnIdentifier, database.getJdbcEnvironment()).render(database.getJdbcEnvironment().getDialect());
}
use of org.hibernate.AnnotationException in project hibernate-orm by hibernate.
the class MapBinder method createFormulatedValue.
protected Value createFormulatedValue(Value value, Collection collection, String targetPropertyName, PersistentClass associatedClass, PersistentClass targetPropertyPersistentClass, MetadataBuildingContext buildingContext) {
Value element = collection.getElement();
String fromAndWhere = null;
if (!(element instanceof OneToMany)) {
String referencedPropertyName = null;
if (element instanceof ToOne) {
referencedPropertyName = ((ToOne) element).getReferencedPropertyName();
} else if (element instanceof DependantValue) {
// TODO this never happen I think
if (propertyName != null) {
referencedPropertyName = collection.getReferencedPropertyName();
} else {
throw new AnnotationException("SecondaryTable JoinColumn cannot reference a non primary key");
}
}
Iterator<Selectable> referencedEntityColumns;
if (referencedPropertyName == null) {
referencedEntityColumns = associatedClass.getIdentifier().getColumnIterator();
} else {
Property referencedProperty = associatedClass.getRecursiveProperty(referencedPropertyName);
referencedEntityColumns = referencedProperty.getColumnIterator();
}
fromAndWhere = getFromAndWhereFormula(associatedClass.getTable().getName(), element.getColumnIterator(), referencedEntityColumns);
} else {
// HHH-11005 - only if we are OneToMany and location of map key property is at a different level, need to add a select
if (!associatedClass.equals(targetPropertyPersistentClass)) {
fromAndWhere = getFromAndWhereFormula(targetPropertyPersistentClass.getTable().getQualifiedTableName().toString(), element.getColumnIterator(), associatedClass.getIdentifier().getColumnIterator());
}
}
if (value instanceof Component) {
Component component = (Component) value;
Iterator properties = component.getPropertyIterator();
Component indexComponent = new Component(getBuildingContext(), collection);
indexComponent.setComponentClassName(component.getComponentClassName());
while (properties.hasNext()) {
Property current = (Property) properties.next();
Property newProperty = new Property();
newProperty.setCascade(current.getCascade());
newProperty.setValueGenerationStrategy(current.getValueGenerationStrategy());
newProperty.setInsertable(false);
newProperty.setUpdateable(false);
newProperty.setMetaAttributes(current.getMetaAttributes());
newProperty.setName(current.getName());
newProperty.setNaturalIdentifier(false);
// newProperty.setOptimisticLocked( false );
newProperty.setOptional(false);
newProperty.setPersistentClass(current.getPersistentClass());
newProperty.setPropertyAccessorName(current.getPropertyAccessorName());
newProperty.setSelectable(current.isSelectable());
newProperty.setValue(createFormulatedValue(current.getValue(), collection, targetPropertyName, associatedClass, associatedClass, buildingContext));
indexComponent.addProperty(newProperty);
}
return indexComponent;
} else if (value instanceof SimpleValue) {
SimpleValue sourceValue = (SimpleValue) value;
SimpleValue targetValue;
if (value instanceof ManyToOne) {
ManyToOne sourceManyToOne = (ManyToOne) sourceValue;
ManyToOne targetManyToOne = new ManyToOne(getBuildingContext(), collection.getCollectionTable());
targetManyToOne.setFetchMode(FetchMode.DEFAULT);
targetManyToOne.setLazy(true);
// targetValue.setIgnoreNotFound( ); does not make sense for a map key
targetManyToOne.setReferencedEntityName(sourceManyToOne.getReferencedEntityName());
targetValue = targetManyToOne;
} else {
targetValue = new SimpleValue(getBuildingContext(), collection.getCollectionTable());
targetValue.copyTypeFrom(sourceValue);
}
Iterator columns = sourceValue.getColumnIterator();
Random random = new Random();
while (columns.hasNext()) {
Object current = columns.next();
Formula formula = new Formula();
String formulaString;
if (current instanceof Column) {
formulaString = ((Column) current).getQuotedName();
} else if (current instanceof Formula) {
formulaString = ((Formula) current).getFormula();
} else {
throw new AssertionFailure("Unknown element in column iterator: " + current.getClass());
}
if (fromAndWhere != null) {
formulaString = Template.renderWhereStringTemplate(formulaString, "$alias$", new HSQLDialect());
formulaString = "(select " + formulaString + fromAndWhere + ")";
formulaString = StringHelper.replace(formulaString, "$alias$", "a" + random.nextInt(16));
}
formula.setFormula(formulaString);
targetValue.addFormula(formula);
}
return targetValue;
} else {
throw new AssertionFailure("Unknown type encounters for map key: " + value.getClass());
}
}
use of org.hibernate.AnnotationException in project hibernate-orm by hibernate.
the class MapBinder method bindKeyFromAssociationTable.
private void bindKeyFromAssociationTable(XClass collType, Map persistentClasses, String mapKeyPropertyName, XProperty property, boolean isEmbedded, MetadataBuildingContext buildingContext, Ejb3Column[] mapKeyColumns, Ejb3JoinColumn[] mapKeyManyToManyColumns, String targetPropertyName) {
if (mapKeyPropertyName != null) {
// this is an EJB3 @MapKey
PersistentClass associatedClass = (PersistentClass) persistentClasses.get(collType.getName());
if (associatedClass == null)
throw new AnnotationException("Associated class not found: " + collType);
Property mapProperty = BinderHelper.findPropertyByName(associatedClass, mapKeyPropertyName);
if (mapProperty == null) {
throw new AnnotationException("Map key property not found: " + collType + "." + mapKeyPropertyName);
}
org.hibernate.mapping.Map map = (org.hibernate.mapping.Map) this.collection;
// HHH-11005 - if InheritanceType.JOINED then need to find class defining the column
InheritanceState inheritanceState = inheritanceStatePerClass.get(collType);
PersistentClass targetPropertyPersistentClass = InheritanceType.JOINED.equals(inheritanceState.getType()) ? mapProperty.getPersistentClass() : associatedClass;
Value indexValue = createFormulatedValue(mapProperty.getValue(), map, targetPropertyName, associatedClass, targetPropertyPersistentClass, buildingContext);
map.setIndex(indexValue);
} else {
// this is a true Map mapping
// TODO ugly copy/pastle from CollectionBinder.bindManyToManySecondPass
String mapKeyType;
Class target = void.class;
/*
* target has priority over reflection for the map key type
* JPA 2 has priority
*/
if (property.isAnnotationPresent(MapKeyClass.class)) {
target = property.getAnnotation(MapKeyClass.class).value();
}
if (!void.class.equals(target)) {
mapKeyType = target.getName();
} else {
mapKeyType = property.getMapKey().getName();
}
PersistentClass collectionEntity = (PersistentClass) persistentClasses.get(mapKeyType);
boolean isIndexOfEntities = collectionEntity != null;
ManyToOne element = null;
org.hibernate.mapping.Map mapValue = (org.hibernate.mapping.Map) this.collection;
if (isIndexOfEntities) {
element = new ManyToOne(buildingContext, mapValue.getCollectionTable());
mapValue.setIndex(element);
element.setReferencedEntityName(mapKeyType);
// element.setFetchMode( fetchMode );
// element.setLazy( fetchMode != FetchMode.JOIN );
// make the second join non lazy
element.setFetchMode(FetchMode.JOIN);
element.setLazy(false);
// does not make sense for a map key element.setIgnoreNotFound( ignoreNotFound );
} else {
XClass keyXClass;
AnnotatedClassType classType;
if (BinderHelper.PRIMITIVE_NAMES.contains(mapKeyType)) {
classType = AnnotatedClassType.NONE;
keyXClass = null;
} else {
try {
keyXClass = buildingContext.getBootstrapContext().getReflectionManager().classForName(mapKeyType);
} catch (ClassLoadingException e) {
throw new AnnotationException("Unable to find class: " + mapKeyType, e);
}
classType = buildingContext.getMetadataCollector().getClassType(keyXClass);
// force in case of attribute override naming the key
if (isEmbedded || mappingDefinedAttributeOverrideOnMapKey(property)) {
classType = AnnotatedClassType.EMBEDDABLE;
}
}
CollectionPropertyHolder holder = PropertyHolderBuilder.buildPropertyHolder(mapValue, StringHelper.qualify(mapValue.getRole(), "mapkey"), keyXClass, property, propertyHolder, buildingContext);
// 'propertyHolder' is the PropertyHolder for the owner of the collection
// 'holder' is the CollectionPropertyHolder.
// 'property' is the collection XProperty
propertyHolder.startingProperty(property);
holder.prepare(property);
PersistentClass owner = mapValue.getOwner();
AccessType accessType;
// String accessType = access != null ? access.value() : null;
if (owner.getIdentifierProperty() != null) {
accessType = owner.getIdentifierProperty().getPropertyAccessorName().equals("property") ? AccessType.PROPERTY : AccessType.FIELD;
} else if (owner.getIdentifierMapper() != null && owner.getIdentifierMapper().getPropertySpan() > 0) {
Property prop = (Property) owner.getIdentifierMapper().getPropertyIterator().next();
accessType = prop.getPropertyAccessorName().equals("property") ? AccessType.PROPERTY : AccessType.FIELD;
} else {
throw new AssertionFailure("Unable to guess collection property accessor name");
}
if (AnnotatedClassType.EMBEDDABLE.equals(classType)) {
EntityBinder entityBinder = new EntityBinder();
PropertyData inferredData;
if (isHibernateExtensionMapping()) {
inferredData = new PropertyPreloadedData(AccessType.PROPERTY, "index", keyXClass);
} else {
// "key" is the JPA 2 prefix for map keys
inferredData = new PropertyPreloadedData(AccessType.PROPERTY, "key", keyXClass);
}
// TODO be smart with isNullable
Component component = AnnotationBinder.fillComponent(holder, inferredData, accessType, true, entityBinder, false, false, true, buildingContext, inheritanceStatePerClass);
mapValue.setIndex(component);
} else {
SimpleValueBinder elementBinder = new SimpleValueBinder();
elementBinder.setBuildingContext(buildingContext);
elementBinder.setReturnedClassName(mapKeyType);
Ejb3Column[] elementColumns = mapKeyColumns;
if (elementColumns == null || elementColumns.length == 0) {
elementColumns = new Ejb3Column[1];
Ejb3Column column = new Ejb3Column();
column.setImplicit(false);
column.setNullable(true);
column.setLength(Ejb3Column.DEFAULT_COLUMN_LENGTH);
column.setLogicalColumnName(Collection.DEFAULT_KEY_COLUMN_NAME);
// TODO create an EMPTY_JOINS collection
column.setJoins(new HashMap<String, Join>());
column.setBuildingContext(buildingContext);
column.bind();
elementColumns[0] = column;
}
// override the table
for (Ejb3Column column : elementColumns) {
column.setTable(mapValue.getCollectionTable());
}
elementBinder.setColumns(elementColumns);
// do not call setType as it extract the type from @Type
// the algorithm generally does not apply for map key anyway
elementBinder.setKey(true);
elementBinder.setType(property, keyXClass, this.collection.getOwnerEntityName(), holder.mapKeyAttributeConverterDescriptor(property, keyXClass));
elementBinder.setPersistentClassName(propertyHolder.getEntityName());
elementBinder.setAccessType(accessType);
mapValue.setIndex(elementBinder.make());
}
}
// FIXME pass the Index Entity JoinColumns
if (!collection.isOneToMany()) {
// index column shoud not be null
for (Ejb3JoinColumn col : mapKeyManyToManyColumns) {
col.forceNotNull();
}
}
if (element != null) {
final javax.persistence.ForeignKey foreignKey = getMapKeyForeignKey(property);
if (foreignKey != null) {
if (foreignKey.value() == ConstraintMode.NO_CONSTRAINT) {
element.setForeignKeyName("none");
} else {
element.setForeignKeyName(StringHelper.nullIfEmpty(foreignKey.name()));
element.setForeignKeyDefinition(StringHelper.nullIfEmpty(foreignKey.foreignKeyDefinition()));
}
}
}
if (isIndexOfEntities) {
bindManytoManyInverseFk(collectionEntity, mapKeyManyToManyColumns, element, // a map key column has no unique constraint
false, buildingContext);
}
}
}
use of org.hibernate.AnnotationException in project hibernate-orm by hibernate.
the class BinderHelper method createSyntheticPropertyReference.
// This is sooooooooo close in terms of not generating a synthetic property if we do not have to (where property ref
// refers to a single property). The sticking point is cases where the `referencedPropertyName` come from subclasses
// or secondary tables. Part of the problem is in PersistentClass itself during attempts to resolve the referenced
// property; currently it only considers non-subclass and non-joined properties. Part of the problem is in terms
// of SQL generation.
// public static void createSyntheticPropertyReference(
// Ejb3JoinColumn[] columns,
// PersistentClass ownerEntity,
// PersistentClass associatedEntity,
// Value value,
// boolean inverse,
// Mappings mappings) {
// //associated entity only used for more precise exception, yuk!
// if ( columns[0].isImplicit() || StringHelper.isNotEmpty( columns[0].getMappedBy() ) ) return;
// int fkEnum = Ejb3JoinColumn.checkReferencedColumnsType( columns, ownerEntity, mappings );
// PersistentClass associatedClass = columns[0].getPropertyHolder() != null ?
// columns[0].getPropertyHolder().getPersistentClass() :
// null;
// if ( Ejb3JoinColumn.NON_PK_REFERENCE == fkEnum ) {
// //find properties associated to a certain column
// Object columnOwner = findColumnOwner( ownerEntity, columns[0].getReferencedColumn(), mappings );
// List<Property> properties = findPropertiesByColumns( columnOwner, columns, mappings );
//
// if ( properties == null ) {
// //TODO use a ToOne type doing a second select
// StringBuilder columnsList = new StringBuilder();
// columnsList.append( "referencedColumnNames(" );
// for (Ejb3JoinColumn column : columns) {
// columnsList.append( column.getReferencedColumn() ).append( ", " );
// }
// columnsList.setLength( columnsList.length() - 2 );
// columnsList.append( ") " );
//
// if ( associatedEntity != null ) {
// //overidden destination
// columnsList.append( "of " )
// .append( associatedEntity.getEntityName() )
// .append( "." )
// .append( columns[0].getPropertyName() )
// .append( " " );
// }
// else {
// if ( columns[0].getPropertyHolder() != null ) {
// columnsList.append( "of " )
// .append( columns[0].getPropertyHolder().getEntityName() )
// .append( "." )
// .append( columns[0].getPropertyName() )
// .append( " " );
// }
// }
// columnsList.append( "referencing " )
// .append( ownerEntity.getEntityName() )
// .append( " not mapped to a single property" );
// throw new AnnotationException( columnsList.toString() );
// }
//
// final String referencedPropertyName;
//
// if ( properties.size() == 1 ) {
// referencedPropertyName = properties.get(0).getName();
// }
// else {
// // Create a synthetic (embedded composite) property to use as the referenced property which
// // contains all the properties mapped to the referenced columns. We need to make a shallow copy
// // of the properties to mark them as non-insertable/updatable.
//
// // todo : what if the columns all match with an existing component?
//
// StringBuilder propertyNameBuffer = new StringBuilder( "_" );
// propertyNameBuffer.append( associatedClass.getEntityName().replace( '.', '_' ) );
// propertyNameBuffer.append( "_" ).append( columns[0].getPropertyName() );
// String syntheticPropertyName = propertyNameBuffer.toString();
// //create an embeddable component
//
// //todo how about properties.size() == 1, this should be much simpler
// Component embeddedComp = columnOwner instanceof PersistentClass ?
// new Component( mappings, (PersistentClass) columnOwner ) :
// new Component( mappings, (Join) columnOwner );
// embeddedComp.setEmbedded( true );
// embeddedComp.setNodeName( syntheticPropertyName );
// embeddedComp.setComponentClassName( embeddedComp.getOwner().getClassName() );
// for (Property property : properties) {
// Property clone = BinderHelper.shallowCopy( property );
// clone.setInsertable( false );
// clone.setUpdateable( false );
// clone.setNaturalIdentifier( false );
// clone.setGeneration( property.getGeneration() );
// embeddedComp.addProperty( clone );
// }
// SyntheticProperty synthProp = new SyntheticProperty();
// synthProp.setName( syntheticPropertyName );
// synthProp.setNodeName( syntheticPropertyName );
// synthProp.setPersistentClass( ownerEntity );
// synthProp.setUpdateable( false );
// synthProp.setInsertable( false );
// synthProp.setValue( embeddedComp );
// synthProp.setPropertyAccessorName( "embedded" );
// ownerEntity.addProperty( synthProp );
// //make it unique
// TableBinder.createUniqueConstraint( embeddedComp );
//
// referencedPropertyName = syntheticPropertyName;
// }
//
// /**
// * creating the property ref to the new synthetic property
// */
// if ( value instanceof ToOne ) {
// ( (ToOne) value ).setReferencedPropertyName( referencedPropertyName );
// mappings.addUniquePropertyReference( ownerEntity.getEntityName(), referencedPropertyName );
// }
// else if ( value instanceof Collection ) {
// ( (Collection) value ).setReferencedPropertyName( referencedPropertyName );
// //not unique because we could create a mtm wo association table
// mappings.addPropertyReference( ownerEntity.getEntityName(), referencedPropertyName );
// }
// else {
// throw new AssertionFailure(
// "Do a property ref on an unexpected Value type: "
// + value.getClass().getName()
// );
// }
// mappings.addPropertyReferencedAssociation(
// ( inverse ? "inverse__" : "" ) + associatedClass.getEntityName(),
// columns[0].getPropertyName(),
// referencedPropertyName
// );
// }
// }
public static void createSyntheticPropertyReference(Ejb3JoinColumn[] columns, PersistentClass ownerEntity, PersistentClass associatedEntity, Value value, boolean inverse, MetadataBuildingContext context) {
// associated entity only used for more precise exception, yuk!
if (columns[0].isImplicit() || StringHelper.isNotEmpty(columns[0].getMappedBy())) {
return;
}
int fkEnum = Ejb3JoinColumn.checkReferencedColumnsType(columns, ownerEntity, context);
PersistentClass associatedClass = columns[0].getPropertyHolder() != null ? columns[0].getPropertyHolder().getPersistentClass() : null;
if (Ejb3JoinColumn.NON_PK_REFERENCE == fkEnum) {
/**
* Create a synthetic property to refer to including an
* embedded component value containing all the properties
* mapped to the referenced columns
* We need to shallow copy those properties to mark them
* as non insertable / non updatable
*/
StringBuilder propertyNameBuffer = new StringBuilder("_");
propertyNameBuffer.append(associatedClass.getEntityName().replace('.', '_'));
propertyNameBuffer.append("_").append(columns[0].getPropertyName().replace('.', '_'));
String syntheticPropertyName = propertyNameBuffer.toString();
// find properties associated to a certain column
Object columnOwner = findColumnOwner(ownerEntity, columns[0].getReferencedColumn(), context);
List<Property> properties = findPropertiesByColumns(columnOwner, columns, context);
// create an embeddable component
Property synthProp;
if (properties != null) {
// todo how about properties.size() == 1, this should be much simpler
Component embeddedComp = columnOwner instanceof PersistentClass ? new Component(context, (PersistentClass) columnOwner) : new Component(context, (Join) columnOwner);
embeddedComp.setEmbedded(true);
embeddedComp.setComponentClassName(embeddedComp.getOwner().getClassName());
for (Property property : properties) {
Property clone = BinderHelper.shallowCopy(property);
clone.setInsertable(false);
clone.setUpdateable(false);
clone.setNaturalIdentifier(false);
clone.setValueGenerationStrategy(property.getValueGenerationStrategy());
embeddedComp.addProperty(clone);
}
synthProp = new SyntheticProperty();
synthProp.setName(syntheticPropertyName);
synthProp.setPersistentClass(ownerEntity);
synthProp.setUpdateable(false);
synthProp.setInsertable(false);
synthProp.setValue(embeddedComp);
synthProp.setPropertyAccessorName("embedded");
ownerEntity.addProperty(synthProp);
// make it unique
TableBinder.createUniqueConstraint(embeddedComp);
} else {
// TODO use a ToOne type doing a second select
StringBuilder columnsList = new StringBuilder();
columnsList.append("referencedColumnNames(");
for (Ejb3JoinColumn column : columns) {
columnsList.append(column.getReferencedColumn()).append(", ");
}
columnsList.setLength(columnsList.length() - 2);
columnsList.append(") ");
if (associatedEntity != null) {
// overidden destination
columnsList.append("of ").append(associatedEntity.getEntityName()).append(".").append(columns[0].getPropertyName()).append(" ");
} else {
if (columns[0].getPropertyHolder() != null) {
columnsList.append("of ").append(columns[0].getPropertyHolder().getEntityName()).append(".").append(columns[0].getPropertyName()).append(" ");
}
}
columnsList.append("referencing ").append(ownerEntity.getEntityName()).append(" not mapped to a single property");
throw new AnnotationException(columnsList.toString());
}
/**
* creating the property ref to the new synthetic property
*/
if (value instanceof ToOne) {
((ToOne) value).setReferencedPropertyName(syntheticPropertyName);
((ToOne) value).setReferenceToPrimaryKey(syntheticPropertyName == null);
context.getMetadataCollector().addUniquePropertyReference(ownerEntity.getEntityName(), syntheticPropertyName);
} else if (value instanceof Collection) {
((Collection) value).setReferencedPropertyName(syntheticPropertyName);
// not unique because we could create a mtm wo association table
context.getMetadataCollector().addPropertyReference(ownerEntity.getEntityName(), syntheticPropertyName);
} else {
throw new AssertionFailure("Do a property ref on an unexpected Value type: " + value.getClass().getName());
}
context.getMetadataCollector().addPropertyReferencedAssociation((inverse ? "inverse__" : "") + associatedClass.getEntityName(), columns[0].getPropertyName(), syntheticPropertyName);
}
}
Aggregations