HHH-6392 Making sure that overrides get applied and adding more tests
This commit is contained in:
parent
593066b7f3
commit
959056dee7
|
@ -12,6 +12,7 @@ import org.hibernate.metamodel.source.annotations.util.JandexHelper;
|
||||||
* are creating during annotation processing and then applied onto the persistence attributes.
|
* are creating during annotation processing and then applied onto the persistence attributes.
|
||||||
*
|
*
|
||||||
* @author Hardy Ferentschik
|
* @author Hardy Ferentschik
|
||||||
|
* @todo Take care of prefixes of the form 'element', 'key' and 'value'. Add another type enum to handle this. (HF)
|
||||||
*/
|
*/
|
||||||
public class AttributeOverride {
|
public class AttributeOverride {
|
||||||
private static final String PROPERTY_PATH_SEPARATOR = ".";
|
private static final String PROPERTY_PATH_SEPARATOR = ".";
|
||||||
|
|
|
@ -80,10 +80,6 @@ public abstract class MappedAttribute implements Comparable<MappedAttribute> {
|
||||||
return typeParameters;
|
return typeParameters;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map<DotName, List<AnnotationInstance>> getAnnotations() {
|
|
||||||
return annotations;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the annotation with the specified name or {@code null}
|
* Returns the annotation with the specified name or {@code null}
|
||||||
*
|
*
|
||||||
|
@ -119,6 +115,10 @@ public abstract class MappedAttribute implements Comparable<MappedAttribute> {
|
||||||
return sb.toString();
|
return sb.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Map<DotName, List<AnnotationInstance>> annotations() {
|
||||||
|
return annotations;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* We need to check whether the is an explicit type specified via {@link org.hibernate.annotations.Type}.
|
* We need to check whether the is an explicit type specified via {@link org.hibernate.annotations.Type}.
|
||||||
*
|
*
|
||||||
|
|
|
@ -91,7 +91,7 @@ public class SimpleAttribute extends MappedAttribute {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static SimpleAttribute createSimpleAttribute(SimpleAttribute simpleAttribute, ColumnValues columnValues) {
|
public static SimpleAttribute createSimpleAttribute(SimpleAttribute simpleAttribute, ColumnValues columnValues) {
|
||||||
SimpleAttribute attribute = new SimpleAttribute( simpleAttribute.getName(), simpleAttribute.getType(), simpleAttribute.getAnnotations(), false );
|
SimpleAttribute attribute = new SimpleAttribute( simpleAttribute.getName(), simpleAttribute.getType(), simpleAttribute.annotations(), false );
|
||||||
attribute.columnValues = columnValues;
|
attribute.columnValues = columnValues;
|
||||||
return attribute;
|
return attribute;
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,10 +47,12 @@ import org.jboss.jandex.ClassInfo;
|
||||||
import org.jboss.jandex.DotName;
|
import org.jboss.jandex.DotName;
|
||||||
import org.jboss.jandex.FieldInfo;
|
import org.jboss.jandex.FieldInfo;
|
||||||
import org.jboss.jandex.MethodInfo;
|
import org.jboss.jandex.MethodInfo;
|
||||||
|
import org.jboss.logging.Logger;
|
||||||
|
|
||||||
import org.hibernate.AnnotationException;
|
import org.hibernate.AnnotationException;
|
||||||
import org.hibernate.AssertionFailure;
|
import org.hibernate.AssertionFailure;
|
||||||
import org.hibernate.HibernateException;
|
import org.hibernate.HibernateException;
|
||||||
|
import org.hibernate.internal.CoreMessageLogger;
|
||||||
import org.hibernate.metamodel.source.annotations.AnnotationBindingContext;
|
import org.hibernate.metamodel.source.annotations.AnnotationBindingContext;
|
||||||
import org.hibernate.metamodel.source.annotations.JPADotNames;
|
import org.hibernate.metamodel.source.annotations.JPADotNames;
|
||||||
import org.hibernate.metamodel.source.annotations.attribute.AssociationAttribute;
|
import org.hibernate.metamodel.source.annotations.attribute.AssociationAttribute;
|
||||||
|
@ -69,6 +71,11 @@ import org.hibernate.metamodel.source.annotations.util.ReflectionHelper;
|
||||||
*/
|
*/
|
||||||
public class ConfiguredClass {
|
public class ConfiguredClass {
|
||||||
|
|
||||||
|
private static final CoreMessageLogger LOG = Logger.getMessageLogger(
|
||||||
|
CoreMessageLogger.class,
|
||||||
|
ConfiguredClass.class.getName()
|
||||||
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The parent of this configured class or {@code null} in case this configured class is the root of a hierarchy.
|
* The parent of this configured class or {@code null} in case this configured class is the root of a hierarchy.
|
||||||
*/
|
*/
|
||||||
|
@ -191,8 +198,8 @@ public class ConfiguredClass {
|
||||||
return attribute;
|
return attribute;
|
||||||
}
|
}
|
||||||
|
|
||||||
public AttributeOverride geAttributeOverrideForPath(String propertyPath) {
|
public Map<String, AttributeOverride> getAttributeOverrideMap() {
|
||||||
return attributeOverrideMap.get( propertyPath );
|
return attributeOverrideMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -320,33 +327,10 @@ public class ConfiguredClass {
|
||||||
|
|
||||||
AccessType accessType = JandexHelper.getValueAsEnum( accessAnnotation, "value", AccessType.class );
|
AccessType accessType = JandexHelper.getValueAsEnum( accessAnnotation, "value", AccessType.class );
|
||||||
|
|
||||||
// when class access type is field
|
if ( !isExplicitAttributeAccessAnnotationPlacedCorrectly( annotationTarget, accessType ) ) {
|
||||||
// overriding access annotations must be placed on properties and have the access type PROPERTY
|
continue;
|
||||||
if ( AccessType.FIELD.equals( classAccessType ) ) {
|
|
||||||
if ( !( annotationTarget instanceof MethodInfo ) ) {
|
|
||||||
// todo log warning !?
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( !AccessType.PROPERTY.equals( accessType ) ) {
|
|
||||||
// todo log warning !?
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// when class access type is property
|
|
||||||
// overriding access annotations must be placed on fields and have the access type FIELD
|
|
||||||
if ( AccessType.PROPERTY.equals( classAccessType ) ) {
|
|
||||||
if ( !( annotationTarget instanceof FieldInfo ) ) {
|
|
||||||
// todo log warning !?
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( !AccessType.FIELD.equals( accessType ) ) {
|
|
||||||
// todo log warning !?
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// the placement is correct, get the member
|
// the placement is correct, get the member
|
||||||
Member member;
|
Member member;
|
||||||
|
@ -386,6 +370,53 @@ public class ConfiguredClass {
|
||||||
return explicitAccessMembers;
|
return explicitAccessMembers;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean isExplicitAttributeAccessAnnotationPlacedCorrectly(AnnotationTarget annotationTarget, AccessType accessType) {
|
||||||
|
// when the access type of the class is FIELD
|
||||||
|
// overriding access annotations must be placed on properties AND have the access type PROPERTY
|
||||||
|
if ( AccessType.FIELD.equals( classAccessType ) ) {
|
||||||
|
if ( !( annotationTarget instanceof MethodInfo ) ) {
|
||||||
|
LOG.tracef(
|
||||||
|
"The access type of class %s is AccessType.FIELD. To override the access for an attribute " +
|
||||||
|
"@Access has to be placed on the property (getter)", classInfo.name().toString()
|
||||||
|
);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( !AccessType.PROPERTY.equals( accessType ) ) {
|
||||||
|
LOG.tracef(
|
||||||
|
"The access type of class %s is AccessType.FIELD. To override the access for an attribute " +
|
||||||
|
"@Access has to be placed on the property (getter) with an access type of AccessType.PROPERTY. " +
|
||||||
|
"Using AccessType.FIELD on the property has no effect",
|
||||||
|
classInfo.name().toString()
|
||||||
|
);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// when the access type of the class is PROPERTY
|
||||||
|
// overriding access annotations must be placed on fields and have the access type FIELD
|
||||||
|
if ( AccessType.PROPERTY.equals( classAccessType ) ) {
|
||||||
|
if ( !( annotationTarget instanceof FieldInfo ) ) {
|
||||||
|
LOG.tracef(
|
||||||
|
"The access type of class %s is AccessType.PROPERTY. To override the access for a field " +
|
||||||
|
"@Access has to be placed on the field ", classInfo.name().toString()
|
||||||
|
);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( !AccessType.FIELD.equals( accessType ) ) {
|
||||||
|
LOG.tracef(
|
||||||
|
"The access type of class %s is AccessType.PROPERTY. To override the access for a field " +
|
||||||
|
"@Access has to be placed on the field with an access type of AccessType.FIELD. " +
|
||||||
|
"Using AccessType.PROPERTY on the field has no effect",
|
||||||
|
classInfo.name().toString()
|
||||||
|
);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
private void createMappedProperty(Member member, ResolvedTypeWithMembers resolvedType) {
|
private void createMappedProperty(Member member, ResolvedTypeWithMembers resolvedType) {
|
||||||
final String attributeName = ReflectionHelper.getPropertyName( member );
|
final String attributeName = ReflectionHelper.getPropertyName( member );
|
||||||
ResolvedMember[] resolvedMembers;
|
ResolvedMember[] resolvedMembers;
|
||||||
|
@ -519,8 +550,13 @@ public class ConfiguredClass {
|
||||||
return resolvedMember.getType().getErasedType();
|
return resolvedMember.getType().getErasedType();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// todo - what to do here
|
throw new AssertionFailure(
|
||||||
return null;
|
String.format(
|
||||||
|
"Unable to resolve type of attribute %s of class %s",
|
||||||
|
name,
|
||||||
|
classInfo.name().toString()
|
||||||
|
)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -613,33 +613,55 @@ public class EntityBinder {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void bindAttributes(EntityBinding entityBinding) {
|
private void bindAttributes(EntityBinding entityBinding) {
|
||||||
|
// collect attribute overrides as we map the attributes
|
||||||
|
Map<String, AttributeOverride> attributeOverrideMap = new HashMap<String, AttributeOverride>();
|
||||||
|
|
||||||
// bind the attributes of this entity
|
// bind the attributes of this entity
|
||||||
AttributeContainer entity = entityBinding.getEntity();
|
AttributeContainer entity = entityBinding.getEntity();
|
||||||
bindAttributes( entityBinding, entity, entityClass, null );
|
bindAttributes( entityBinding, entity, entityClass, attributeOverrideMap );
|
||||||
|
|
||||||
// bind potential mapped super class attributes
|
// bind potential mapped super class attributes
|
||||||
ConfiguredClass childClass = entityClass;
|
attributeOverrideMap.putAll( entityClass.getAttributeOverrideMap() );
|
||||||
ConfiguredClass parent = entityClass.getParent();
|
ConfiguredClass parent = entityClass.getParent();
|
||||||
Hierarchical superTypeContainer = entityBinding.getEntity().getSuperType();
|
Hierarchical superTypeContainer = entityBinding.getEntity().getSuperType();
|
||||||
while ( containsPotentialMappedSuperclassAttributes( parent ) ) {
|
while ( containsMappedSuperclassAttributes( parent ) ) {
|
||||||
bindAttributes( entityBinding, superTypeContainer, parent, childClass );
|
bindAttributes( entityBinding, superTypeContainer, parent, attributeOverrideMap );
|
||||||
childClass = parent;
|
addNewOverridesToMap( parent, attributeOverrideMap );
|
||||||
parent = parent.getParent();
|
parent = parent.getParent();
|
||||||
superTypeContainer = superTypeContainer.getSuperType();
|
superTypeContainer = superTypeContainer.getSuperType();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean containsPotentialMappedSuperclassAttributes(ConfiguredClass parent) {
|
private void addNewOverridesToMap(ConfiguredClass parent, Map<String, AttributeOverride> attributeOverrideMap) {
|
||||||
|
Map<String, AttributeOverride> overrides = parent.getAttributeOverrideMap();
|
||||||
|
for ( Map.Entry<String, AttributeOverride> entry : overrides.entrySet() ) {
|
||||||
|
if ( !attributeOverrideMap.containsKey( entry.getKey() ) ) {
|
||||||
|
attributeOverrideMap.put( entry.getKey(), entry.getValue() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean containsMappedSuperclassAttributes(ConfiguredClass parent) {
|
||||||
return parent != null && ( ConfiguredClassType.MAPPED_SUPERCLASS.equals( parent.getConfiguredClassType() ) ||
|
return parent != null && ( ConfiguredClassType.MAPPED_SUPERCLASS.equals( parent.getConfiguredClassType() ) ||
|
||||||
ConfiguredClassType.NON_ENTITY.equals( parent.getConfiguredClassType() ) );
|
ConfiguredClassType.NON_ENTITY.equals( parent.getConfiguredClassType() ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
private void bindAttributes(EntityBinding entityBinding, AttributeContainer attributeContainer, ConfiguredClass configuredClass, ConfiguredClass childClass) {
|
/**
|
||||||
|
* Creates attribute bindings for the attributes of {@code configuredClass}
|
||||||
|
*
|
||||||
|
* @param entityBinding The entity binding for the class we are currently binding
|
||||||
|
* @param attributeContainer The domain attribute container to which to add the attribute (could be the entity itself, or a mapped super class
|
||||||
|
* or a component)
|
||||||
|
* @param configuredClass the configured containing the attributes to be bound
|
||||||
|
* @param attributeOverrideMap a map with the accumulated attribute overrides
|
||||||
|
*/
|
||||||
|
private void bindAttributes(EntityBinding entityBinding, AttributeContainer attributeContainer, ConfiguredClass configuredClass, Map<String, AttributeOverride> attributeOverrideMap) {
|
||||||
for ( SimpleAttribute simpleAttribute : configuredClass.getSimpleAttributes() ) {
|
for ( SimpleAttribute simpleAttribute : configuredClass.getSimpleAttributes() ) {
|
||||||
String attributeName = simpleAttribute.getName();
|
String attributeName = simpleAttribute.getName();
|
||||||
|
|
||||||
if(childClass != null && childClass.geAttributeOverrideForPath(attributeName) != null) {
|
// if there is a override apply it
|
||||||
AttributeOverride override = childClass.geAttributeOverrideForPath(attributeName);
|
AttributeOverride override = attributeOverrideMap.get( attributeName );
|
||||||
|
if ( override != null ) {
|
||||||
simpleAttribute = SimpleAttribute.createSimpleAttribute( simpleAttribute, override.getColumnValues() );
|
simpleAttribute = SimpleAttribute.createSimpleAttribute( simpleAttribute, override.getColumnValues() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -665,7 +687,7 @@ public class EntityBinder {
|
||||||
// bind potential mapped super class embeddables
|
// bind potential mapped super class embeddables
|
||||||
ConfiguredClass parent = entityClass.getParent();
|
ConfiguredClass parent = entityClass.getParent();
|
||||||
Hierarchical superTypeContainer = entityBinding.getEntity().getSuperType();
|
Hierarchical superTypeContainer = entityBinding.getEntity().getSuperType();
|
||||||
while ( containsPotentialMappedSuperclassAttributes( parent ) ) {
|
while ( containsMappedSuperclassAttributes( parent ) ) {
|
||||||
bindEmbeddedAttributes( entityBinding, superTypeContainer, parent );
|
bindEmbeddedAttributes( entityBinding, superTypeContainer, parent );
|
||||||
parent = parent.getParent();
|
parent = parent.getParent();
|
||||||
superTypeContainer = superTypeContainer.getSuperType();
|
superTypeContainer = superTypeContainer.getSuperType();
|
||||||
|
|
|
@ -25,8 +25,6 @@ package org.hibernate.metamodel.source.annotations.entity;
|
||||||
|
|
||||||
import javax.persistence.AttributeOverride;
|
import javax.persistence.AttributeOverride;
|
||||||
import javax.persistence.AttributeOverrides;
|
import javax.persistence.AttributeOverrides;
|
||||||
import javax.persistence.Embeddable;
|
|
||||||
import javax.persistence.Embedded;
|
|
||||||
import javax.persistence.Entity;
|
import javax.persistence.Entity;
|
||||||
import javax.persistence.Id;
|
import javax.persistence.Id;
|
||||||
import javax.persistence.MappedSuperclass;
|
import javax.persistence.MappedSuperclass;
|
||||||
|
@ -36,11 +34,9 @@ import org.junit.Test;
|
||||||
import org.hibernate.metamodel.binding.AttributeBinding;
|
import org.hibernate.metamodel.binding.AttributeBinding;
|
||||||
import org.hibernate.metamodel.binding.EntityBinding;
|
import org.hibernate.metamodel.binding.EntityBinding;
|
||||||
import org.hibernate.metamodel.domain.NonEntity;
|
import org.hibernate.metamodel.domain.NonEntity;
|
||||||
import org.hibernate.metamodel.domain.Superclass;
|
|
||||||
import org.hibernate.metamodel.relational.Column;
|
import org.hibernate.metamodel.relational.Column;
|
||||||
import org.hibernate.metamodel.relational.SimpleValue;
|
import org.hibernate.metamodel.relational.SimpleValue;
|
||||||
import org.hibernate.metamodel.relational.Tuple;
|
import org.hibernate.metamodel.relational.Tuple;
|
||||||
import org.hibernate.testing.FailureExpected;
|
|
||||||
|
|
||||||
import static junit.framework.Assert.assertEquals;
|
import static junit.framework.Assert.assertEquals;
|
||||||
import static junit.framework.Assert.assertNotNull;
|
import static junit.framework.Assert.assertNotNull;
|
||||||
|
@ -54,34 +50,37 @@ import static junit.framework.Assert.assertTrue;
|
||||||
*/
|
*/
|
||||||
public class MappedSuperclassTests extends BaseAnnotationBindingTestCase {
|
public class MappedSuperclassTests extends BaseAnnotationBindingTestCase {
|
||||||
@Test
|
@Test
|
||||||
public void testMappedSuperclass() {
|
public void testSimpleAttributeOverrideInMappedSuperclass() {
|
||||||
buildMetadataSources( MyMappedSuperClass.class, MyEntity.class, Address.class );
|
buildMetadataSources( MyMappedSuperClass.class, MyEntity.class, MyMappedSuperClassBase.class );
|
||||||
|
|
||||||
EntityBinding binding = getEntityBinding( MyEntity.class );
|
EntityBinding binding = getEntityBinding( MyEntity.class );
|
||||||
assertEquals( "Wrong entity name", MyEntity.class.getName(), binding.getEntity().getName() );
|
|
||||||
assertEquals(
|
|
||||||
"Wrong entity name",
|
|
||||||
MyMappedSuperClass.class.getName(),
|
|
||||||
binding.getEntity().getSuperType().getName()
|
|
||||||
);
|
|
||||||
|
|
||||||
assertTrue( binding.getEntity().getSuperType() instanceof Superclass );
|
|
||||||
AttributeBinding nameBinding = binding.getAttributeBinding( "name" );
|
AttributeBinding nameBinding = binding.getAttributeBinding( "name" );
|
||||||
assertNotNull( "the name attribute should be bound to the subclass", nameBinding );
|
assertNotNull( "the name attribute should be bound to MyEntity", nameBinding );
|
||||||
|
|
||||||
assertTrue( "The binding should be a simple column", nameBinding.getValue() instanceof Tuple );
|
|
||||||
Tuple tuple = (Tuple) nameBinding.getValue();
|
Tuple tuple = (Tuple) nameBinding.getValue();
|
||||||
SimpleValue value = tuple.values().iterator().next();
|
SimpleValue value = tuple.values().iterator().next();
|
||||||
assertTrue( value instanceof Column );
|
assertTrue( value instanceof Column );
|
||||||
Column column = (Column) value;
|
Column column = (Column) value;
|
||||||
assertEquals( "Wrong column name", "`MY_NAME`", column.getColumnName().toString() );
|
assertEquals( "Wrong column name", "`MY_NAME`", column.getColumnName().toString() );
|
||||||
|
|
||||||
AttributeBinding idBinding = binding.getEntityIdentifier().getValueBinding();
|
|
||||||
assertNotNull( "the id attribute should be bound", idBinding );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testNoEntity() {
|
public void testLastAttributeOverrideWins() {
|
||||||
|
buildMetadataSources( MyMappedSuperClass.class, MyEntity.class, MyMappedSuperClassBase.class );
|
||||||
|
|
||||||
|
EntityBinding binding = getEntityBinding( MyEntity.class );
|
||||||
|
AttributeBinding fooBinding = binding.getAttributeBinding( "foo" );
|
||||||
|
assertNotNull( "the foo attribute should be bound to MyEntity", fooBinding );
|
||||||
|
|
||||||
|
Tuple tuple = (Tuple) fooBinding.getValue();
|
||||||
|
SimpleValue value = tuple.values().iterator().next();
|
||||||
|
assertTrue( value instanceof Column );
|
||||||
|
Column column = (Column) value;
|
||||||
|
assertEquals( "Wrong column name", "`MY_FOO`", column.getColumnName().toString() );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testNonEntityBaseClass() {
|
||||||
buildMetadataSources( SubclassOfNoEntity.class, NoEntity.class );
|
buildMetadataSources( SubclassOfNoEntity.class, NoEntity.class );
|
||||||
EntityBinding binding = getEntityBinding( SubclassOfNoEntity.class );
|
EntityBinding binding = getEntityBinding( SubclassOfNoEntity.class );
|
||||||
assertEquals( "Wrong entity name", SubclassOfNoEntity.class.getName(), binding.getEntity().getName() );
|
assertEquals( "Wrong entity name", SubclassOfNoEntity.class.getName(), binding.getEntity().getName() );
|
||||||
|
@ -90,28 +89,26 @@ public class MappedSuperclassTests extends BaseAnnotationBindingTestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
@MappedSuperclass
|
@MappedSuperclass
|
||||||
class MyMappedSuperClass {
|
class MyMappedSuperClassBase {
|
||||||
@Id
|
@Id
|
||||||
private int id;
|
private int id;
|
||||||
|
String foo;
|
||||||
|
}
|
||||||
|
|
||||||
|
@MappedSuperclass
|
||||||
|
@AttributeOverride(name = "foo", column = @javax.persistence.Column(name = "SUPER_FOO"))
|
||||||
|
class MyMappedSuperClass extends MyMappedSuperClassBase {
|
||||||
String name;
|
String name;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Entity
|
@Entity
|
||||||
@AttributeOverrides( {
|
@AttributeOverrides( {
|
||||||
@AttributeOverride(name = "name", column = @javax.persistence.Column(name = "MY_NAME")),
|
@AttributeOverride(name = "name", column = @javax.persistence.Column(name = "MY_NAME")),
|
||||||
@AttributeOverride(name = "address.street", column = @javax.persistence.Column(name = "MY_STREET"))
|
@AttributeOverride(name = "foo", column = @javax.persistence.Column(name = "MY_FOO"))
|
||||||
})
|
})
|
||||||
class MyEntity extends MyMappedSuperClass {
|
class MyEntity extends MyMappedSuperClass {
|
||||||
private Long count;
|
private Long count;
|
||||||
@AttributeOverride(name = "city", column = @javax.persistence.Column(name = "MY_CITY"))
|
|
||||||
@Embedded
|
|
||||||
Address address;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Embeddable
|
|
||||||
class Address {
|
|
||||||
String street;
|
|
||||||
String city;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class NoEntity {
|
class NoEntity {
|
||||||
|
|
Loading…
Reference in New Issue