Skip to content

Commit

Permalink
HHH-9055 - Binding support for IdClass and MapsId needs a complete re…
Browse files Browse the repository at this point in the history
…view
  • Loading branch information
sebersole committed Apr 24, 2014
1 parent 700a233 commit 104eea1
Show file tree
Hide file tree
Showing 15 changed files with 399 additions and 14 deletions.
Expand Up @@ -18,17 +18,24 @@
import org.hibernate.metamodel.spi.SingularAttributeNature;
import org.hibernate.type.ForeignKeyDirection;

import org.jboss.jandex.AnnotationInstance;
import org.jboss.jandex.AnnotationValue;

public abstract class AbstractToOneAttributeSourceImpl extends SingularAttributeSourceImpl implements ToOneAttributeSource{
private final SingularAssociationAttribute associationAttribute;
private final Set<CascadeStyle> unifiedCascadeStyles;

private SingularAttributeNature singularAttributeNature;
private final Set<MappedByAssociationSource> ownedAssociationSources = new HashSet<MappedByAssociationSource>();

private final MapsIdSourceImpl mapsIdSource;

public AbstractToOneAttributeSourceImpl(SingularAssociationAttribute associationAttribute) {
super( associationAttribute );
this.associationAttribute = associationAttribute;
this.unifiedCascadeStyles = determineCascadeStyles( associationAttribute );

this.mapsIdSource = MapsIdSourceImpl.interpret( associationAttribute.getMapsIdAnnotation() );
}

private static Set<CascadeStyle> determineCascadeStyles(SingularAssociationAttribute associationAttribute) {
Expand Down Expand Up @@ -146,4 +153,39 @@ public AttributePath getAttributePath() {
public AttributeRole getAttributeRole() {
return associationAttribute.getRole();
}

@Override
public MapsIdSource getMapsIdSource() {
return mapsIdSource;
}

private static class MapsIdSourceImpl implements MapsIdSource {
private final boolean present;
private final String name;

public static MapsIdSourceImpl interpret(AnnotationInstance mapsIdAnnotation) {
if ( mapsIdAnnotation == null ) {
return new MapsIdSourceImpl( false, null );
}

final AnnotationValue value = mapsIdAnnotation.value();
final String name = value == null ? null : value.asString();
return new MapsIdSourceImpl( true, name );
}

private MapsIdSourceImpl(boolean present, String name) {
this.present = present;
this.name = name;
}

@Override
public boolean isDefined() {
return present;
}

@Override
public String getLookupClassAttributeName() {
return name;
}
}
}
Expand Up @@ -89,7 +89,9 @@ public ToOneAttributeSourceImpl(
this.containingTableName = resolveContainingTableName( associationAttribute, relationalValueSources );
setSingularAttributeNature( determineNatureIfPossible( associationAttribute ) );
this.foreignKeyDelegate = new ForeignKeyDelegate(
associationAttribute().getBackingMember().getAnnotations(), cls);
associationAttribute().getBackingMember().getAnnotations(),
cls
);
}

private SingularAttributeNature determineNatureIfPossible(
Expand Down
Expand Up @@ -173,9 +173,7 @@ public PluralAttribute(

this.classLoaderService = getContext().getServiceRegistry().getService( ClassLoaderService.class );

// just to get the error the test expects
// todo : I'd really rather see this driven from the class-level, not the attribute-level
AssociationHelper.INSTANCE.determineMapsId(
AssociationHelper.INSTANCE.locateMapsId(
backingMember,
attributeNature,
container.getLocalBindingContext()
Expand Down
Expand Up @@ -67,7 +67,7 @@ public class SingularAssociationAttribute
private ArrayList<Column> joinColumnValues = new ArrayList<Column>();
private ArrayList<Column> inverseJoinColumnValues = new ArrayList<Column>();

private final String mapsIdAttributeName;
private final AnnotationInstance mapsIdAnnotation;

private final boolean hasPrimaryKeyJoinColumn;

Expand Down Expand Up @@ -121,7 +121,7 @@ public SingularAssociationAttribute(
this.isOrphanRemoval = AssociationHelper.INSTANCE.determineOrphanRemoval( associationAnnotation );
this.ignoreNotFound = AssociationHelper.INSTANCE.determineWhetherToIgnoreNotFound( backingMember );

this.mapsIdAttributeName = AssociationHelper.INSTANCE.determineMapsId(
this.mapsIdAnnotation = AssociationHelper.INSTANCE.locateMapsId(
backingMember,
attributeNature,
container.getLocalBindingContext()
Expand Down Expand Up @@ -262,4 +262,8 @@ public ArrayList<Column> getJoinColumnValues() {
public ArrayList<Column> getInverseJoinColumnValues() {
return inverseJoinColumnValues;
}

public AnnotationInstance getMapsIdAnnotation() {
return mapsIdAnnotation;
}
}
Expand Up @@ -258,7 +258,7 @@ public boolean determineOrphanRemoval(AnnotationInstance associationAnnotation)
return false;
}

public String determineMapsId(
public AnnotationInstance locateMapsId(
MemberDescriptor member,
PersistentAttribute.Nature attributeNature,
EntityBindingContext localBindingContext) {
Expand All @@ -275,9 +275,7 @@ public String determineMapsId(
"associations, property: " + member.toString()
);
}
return mapsIdAnnotation.value() == null
? null
: mapsIdAnnotation.value().asString();
return mapsIdAnnotation;
}

public boolean determineWhetherToIgnoreNotFound(MemberDescriptor backingMember) {
Expand Down
Expand Up @@ -269,4 +269,25 @@ public boolean createForeignKeyConstraint() {
return true;
}

@Override
public MapsIdSource getMapsIdSource() {
return MapsIdSourceImpl.INSTANCE;
}

private static class MapsIdSourceImpl implements MapsIdSource {
/**
* Singleton access
*/
public static final MapsIdSourceImpl INSTANCE = new MapsIdSourceImpl();

@Override
public boolean isDefined() {
return false;
}

@Override
public String getLookupClassAttributeName() {
return null;
}
}
}
Expand Up @@ -41,8 +41,29 @@ public interface ToOneAttributeSource
FetchableAttributeSource,
AssociationSource {

public MapsIdSource getMapsIdSource();

public boolean isUnique();
public boolean isUnWrapProxy();
ForeignKeyDirection getForeignKeyDirection();
public List<Binder.DefaultNamingStrategy> getDefaultNamingStrategies(final String entityName, final String tableName, final AttributeBinding referencedAttributeBinding);

/**
* Source for JPA {@link javax.persistence.MapsId} annotation information
*/
public static interface MapsIdSource {
/**
* Was a MapsId annotation present on the to-one?
*
* @return {@code true} if MapsId annotation was present; {@code false} otherwise.
*/
public boolean isDefined();

/**
* The {@link javax.persistence.MapsId#value()} value.
*
* @return The indicated name
*/
public String getLookupClassAttributeName();
}
}
Expand Up @@ -65,11 +65,12 @@
*/
public class EntityIdentifier {
private final EntityBinding entityBinding;
private EntityIdentifierBinding entityIdentifierBinding;
private IdentifierGenerator identifierGenerator;

private Binding binding;
private LookupClassBinding lookupClassBinding;

private IdentifierGenerator identifierGenerator;

/**
* Create an identifier
*
Expand Down Expand Up @@ -140,7 +141,7 @@ public LookupClassBinding getLookupClassBinding() {

public EntityIdentifierNature getNature() {
ensureBound();
return entityIdentifierBinding.getNature();
return binding.getNature();
}

public SingularAttributeBinding getAttributeBinding() {
Expand All @@ -163,7 +164,7 @@ public boolean isCascadeDeleteEnabled() {

public String getUnsavedValue() {
ensureBound();
return entityIdentifierBinding.getUnsavedValue();
return binding.getUnsavedValue();
}

public boolean isNonAggregatedComposite() {
Expand Down Expand Up @@ -590,4 +591,12 @@ public Serializable locateGenerationContext( SessionImplementor session, Object
}
}

public static interface Binding {
public EntityIdentifierNature getNature();

public String getUnsavedValue();

public IdentifierGeneratorDefinition getGeneratorDefinition();
}

}
@@ -0,0 +1,38 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2014, Red Hat Inc. or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Inc.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.test.metamodel.derivedid.e1;

import javax.persistence.Entity;
import javax.persistence.Id;

/**
* Taken from "Example 1" of the JPA spec on derived identities.
*
* @author Steve Ebersole
*/
@Entity
public class Employee {
@Id long empId;
String empName;
}
@@ -0,0 +1,44 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2014, Red Hat Inc. or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Inc.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.test.metamodel.derivedid.e1.a;

import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.IdClass;
import javax.persistence.ManyToOne;

import org.hibernate.test.metamodel.derivedid.e1.Employee;

/**
* @author Steve Ebersole
*/
@Entity
@IdClass(DependentId.class)
public class Dependent {
@Id
String name;

@Id @ManyToOne
Employee emp;
}
@@ -0,0 +1,32 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2014, Red Hat Inc. or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Inc.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.test.metamodel.derivedid.e1.a;

/**
* @author Steve Ebersole
*/
public class DependentId {
String name; // matches name of @Id attribute
long emp; // matches name of @Id attribute and type of Employee PK
}

0 comments on commit 104eea1

Please sign in to comment.