HHH-5832 : JPA Query and IdClass Causing NullPointerException
This commit is contained in:
parent
e14e47968f
commit
3c4ed4fe6b
|
@ -23,6 +23,7 @@
|
|||
*/
|
||||
package org.hibernate.ejb.metamodel;
|
||||
import java.io.Serializable;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import javax.persistence.metamodel.Attribute;
|
||||
import javax.persistence.metamodel.IdentifiableType;
|
||||
|
@ -68,6 +69,17 @@ public abstract class AbstractIdentifiableType<X>
|
|||
return ( AbstractIdentifiableType<? super X> ) super.getSupertype();
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if a non-null super type is required to provide the
|
||||
* identifier attribute(s) if this object does not have a declared
|
||||
* identifier.
|
||||
* .
|
||||
* @return true, if a non-null super type is required to provide
|
||||
* the identifier attribute(s) if this object does not have a
|
||||
* declared identifier; false, otherwise.
|
||||
*/
|
||||
protected abstract boolean requiresSupertypeForNonDeclaredIdentifier();
|
||||
|
||||
protected AbstractIdentifiableType<? super X> requireSupertype() {
|
||||
if ( getSupertype() == null ) {
|
||||
throw new IllegalStateException( "No supertype found" );
|
||||
|
@ -97,7 +109,7 @@ public abstract class AbstractIdentifiableType<X>
|
|||
}
|
||||
else {
|
||||
//yuk yuk bad me
|
||||
if (this instanceof MappedSuperclassTypeImpl) {
|
||||
if ( ! requiresSupertypeForNonDeclaredIdentifier()) {
|
||||
final AbstractIdentifiableType<? super X> supertype = getSupertype();
|
||||
if (supertype != null) {
|
||||
id_ = supertype.getId( javaType );
|
||||
|
@ -162,11 +174,33 @@ public abstract class AbstractIdentifiableType<X>
|
|||
}
|
||||
}
|
||||
|
||||
private boolean hasIdClassAttributesDefined() {
|
||||
return idClassAttributes != null ||
|
||||
( getSupertype() != null && getSupertype().hasIdClassAttributesDefined() );
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public Set<SingularAttribute<? super X, ?>> getIdClassAttributes() {
|
||||
checkIdClass();
|
||||
if ( idClassAttributes != null ) {
|
||||
checkIdClass();
|
||||
}
|
||||
else {
|
||||
// Java does not allow casting requireSupertype().getIdClassAttributes()
|
||||
// to Set<SingularAttribute<? super X, ?>> because the
|
||||
// superclass X is a different Java type from this X
|
||||
// (i.e, getSupertype().getJavaType() != getJavaType()).
|
||||
// It will, however, allow a Set<SingularAttribute<? super X, ?>>
|
||||
// to be initialized with requireSupertype().getIdClassAttributes(),
|
||||
// since getSupertype().getJavaType() is a superclass of getJavaType()
|
||||
if ( requiresSupertypeForNonDeclaredIdentifier() ) {
|
||||
idClassAttributes = new HashSet<SingularAttribute<? super X, ?>>( requireSupertype().getIdClassAttributes() );
|
||||
}
|
||||
else if ( getSupertype() != null && hasIdClassAttributesDefined() ) {
|
||||
idClassAttributes = new HashSet<SingularAttribute<? super X, ?>>( getSupertype().getIdClassAttributes() );
|
||||
}
|
||||
}
|
||||
return idClassAttributes;
|
||||
}
|
||||
|
||||
|
@ -254,6 +288,13 @@ public abstract class AbstractIdentifiableType<X>
|
|||
}
|
||||
|
||||
public void applyIdClassAttributes(Set<SingularAttribute<? super X,?>> idClassAttributes) {
|
||||
for ( SingularAttribute<? super X,?> idClassAttribute : idClassAttributes ) {
|
||||
if ( AbstractIdentifiableType.this == idClassAttribute.getDeclaringType() ) {
|
||||
@SuppressWarnings({ "unchecked" })
|
||||
SingularAttribute<X,?> declaredAttribute = ( SingularAttribute<X,?> ) idClassAttribute;
|
||||
addAttribute( declaredAttribute );
|
||||
}
|
||||
}
|
||||
AbstractIdentifiableType.this.idClassAttributes = idClassAttributes;
|
||||
}
|
||||
|
||||
|
|
|
@ -59,4 +59,9 @@ public class EntityTypeImpl<X>
|
|||
public PersistenceType getPersistenceType() {
|
||||
return PersistenceType.ENTITY;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean requiresSupertypeForNonDeclaredIdentifier() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,4 +16,9 @@ public class MappedSuperclassTypeImpl<X> extends AbstractIdentifiableType<X> imp
|
|||
public PersistenceType getPersistenceType() {
|
||||
return PersistenceType.MAPPED_SUPERCLASS;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean requiresSupertypeForNonDeclaredIdentifier() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -244,7 +244,10 @@ class MetadataContext {
|
|||
}
|
||||
}
|
||||
else if ( persistentClass.hasIdentifierMapper() ) {
|
||||
jpaEntityType.getBuilder().applyIdClassAttributes( buildIdClassAttributes( jpaEntityType, persistentClass ) );
|
||||
@SuppressWarnings( "unchecked")
|
||||
Iterator<Property> propertyIterator = persistentClass.getIdentifierMapper().getPropertyIterator();
|
||||
Set<SingularAttribute<? super X, ?>> attributes = buildIdClassAttributes( jpaEntityType, propertyIterator );
|
||||
jpaEntityType.getBuilder().applyIdClassAttributes( attributes );
|
||||
}
|
||||
else {
|
||||
final KeyValue value = persistentClass.getIdentifier();
|
||||
|
@ -276,9 +279,9 @@ class MetadataContext {
|
|||
}
|
||||
//an MappedSuperclass can have no identifier if the id is set below in the hierarchy
|
||||
else if ( mappingType.getIdentifierMapper() != null ){
|
||||
final Set<SingularAttribute<? super X, ?>> attributes = buildIdClassAttributes(
|
||||
jpaMappingType, mappingType
|
||||
);
|
||||
@SuppressWarnings( "unchecked")
|
||||
Iterator<Property> propertyIterator = mappingType.getIdentifierMapper().getPropertyIterator();
|
||||
Set<SingularAttribute<? super X, ?>> attributes = buildIdClassAttributes( jpaMappingType, propertyIterator );
|
||||
jpaMappingType.getBuilder().applyIdClassAttributes( attributes );
|
||||
}
|
||||
}
|
||||
|
@ -302,26 +305,12 @@ class MetadataContext {
|
|||
}
|
||||
|
||||
private <X> Set<SingularAttribute<? super X, ?>> buildIdClassAttributes(
|
||||
EntityTypeImpl<X> jpaEntityType,
|
||||
PersistentClass persistentClass) {
|
||||
Set<SingularAttribute<? super X, ?>> attributes = new HashSet<SingularAttribute<? super X, ?>>();
|
||||
@SuppressWarnings( "unchecked")
|
||||
Iterator<Property> properties = persistentClass.getIdentifierMapper().getPropertyIterator();
|
||||
while ( properties.hasNext() ) {
|
||||
attributes.add( attributeFactory.buildIdAttribute( jpaEntityType, properties.next() ) );
|
||||
}
|
||||
return attributes;
|
||||
}
|
||||
|
||||
private <X> Set<SingularAttribute<? super X, ?>> buildIdClassAttributes(
|
||||
MappedSuperclassTypeImpl<X> jpaMappingType,
|
||||
MappedSuperclass mappingType) {
|
||||
LOG.trace("Building old-school composite identifier [" + mappingType.getMappedClass().getName() + "]");
|
||||
Set<SingularAttribute<? super X, ?>> attributes = new HashSet<SingularAttribute<? super X, ?>>();
|
||||
@SuppressWarnings( "unchecked" )
|
||||
Iterator<Property> properties = mappingType.getIdentifierMapper().getPropertyIterator();
|
||||
while ( properties.hasNext() ) {
|
||||
attributes.add( attributeFactory.buildIdAttribute( jpaMappingType, properties.next() ) );
|
||||
AbstractIdentifiableType<X> ownerType,
|
||||
Iterator<Property> propertyIterator) {
|
||||
LOG.trace("Building old-school composite identifier [" + ownerType.getJavaType().getName() + "]");
|
||||
Set<SingularAttribute<? super X, ?>> attributes = new HashSet<SingularAttribute<? super X, ?>>();
|
||||
while ( propertyIterator.hasNext() ) {
|
||||
attributes.add( attributeFactory.buildIdAttribute( ownerType, propertyIterator.next() ) );
|
||||
}
|
||||
return attributes;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2011, 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.ejb.criteria.idclass;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.IdClass;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.MappedSuperclass;
|
||||
import javax.persistence.Table;
|
||||
|
||||
/**
|
||||
* @author Erich Heard
|
||||
*/
|
||||
@MappedSuperclass
|
||||
@Table( name = "HELPER" )
|
||||
@IdClass( org.hibernate.ejb.criteria.idclass.HelperId.class )
|
||||
public class Helper {
|
||||
@Id
|
||||
private String name;
|
||||
public String getName( ) { return this.name; }
|
||||
public void setName( String value ) { this.name = value; }
|
||||
|
||||
@Id
|
||||
private String type;
|
||||
public String getType( ) { return this.type; }
|
||||
public void setType( String value ) { this.type = value; }
|
||||
|
||||
@Override
|
||||
public String toString( ) {
|
||||
return "[Name:" + this.getName( ) + "; Type: " + this.getType( ) + "]";
|
||||
}
|
||||
}
|
|
@ -0,0 +1,77 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2011, 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.ejb.criteria.idclass;
|
||||
|
||||
import java.io.Serializable;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Embeddable;
|
||||
import javax.persistence.Id;
|
||||
|
||||
/**
|
||||
* @author Gail Badner
|
||||
*/
|
||||
|
||||
@Embeddable
|
||||
public class HelperId implements Serializable {
|
||||
private static final long serialVersionUID = 9122480802791185646L;
|
||||
|
||||
@Id
|
||||
@Column( name = "NAME", length = 12 )
|
||||
private String name;
|
||||
public String getName( ) { return this.name; }
|
||||
public void setName( String value ) { this.name = value; }
|
||||
|
||||
@Id
|
||||
@Column( name = "HELPER_TYPE", length = 4 )
|
||||
private String type;
|
||||
public String getType( ) { return this.type; }
|
||||
public void setType( String value ) { this.type = value; }
|
||||
|
||||
@Override
|
||||
public boolean equals( Object obj ) {
|
||||
if( obj == null ) return false;
|
||||
if( !( obj instanceof HelperId ) ) return false;
|
||||
|
||||
HelperId id = ( HelperId )obj;
|
||||
if( this.getName() == null || id.getName() == null || this.getType() == null || id.getType() == null ) return false;
|
||||
|
||||
return this.toString( ).equals( id.toString( ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode( ) {
|
||||
return this.toString( ).hashCode( );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString( ) {
|
||||
StringBuilder buf = new StringBuilder( "[id:" );
|
||||
buf.append( ( this.getName() == null ) ? "null" : this.getName( ) );
|
||||
buf.append( ";type:" );
|
||||
buf.append( ( this.getType() == null ) ? "null" : this.getType() );
|
||||
buf.append( "]" );
|
||||
|
||||
return buf.toString( );
|
||||
}
|
||||
}
|
|
@ -0,0 +1,195 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2011, 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.ejb.criteria.idclass;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import javax.persistence.*;
|
||||
import javax.persistence.criteria.*;
|
||||
|
||||
import junit.framework.Assert;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.hibernate.ejb.metamodel.AbstractMetamodelSpecificTest;
|
||||
|
||||
/**
|
||||
* @author Erich Heard
|
||||
*/
|
||||
public class IdClassPredicateTest extends AbstractMetamodelSpecificTest {
|
||||
|
||||
@Override
|
||||
public Class[] getAnnotatedClasses() {
|
||||
return new Class[] {
|
||||
Widget.class,
|
||||
Tool.class
|
||||
};
|
||||
}
|
||||
|
||||
@Before
|
||||
public void prepareTestData() {
|
||||
EntityManager em = entityManagerFactory().createEntityManager();
|
||||
em.getTransaction().begin();
|
||||
|
||||
Widget w = new Widget();
|
||||
w.setCode( "AAA" );
|
||||
w.setDivision( "NA" );
|
||||
w.setCost( 10.00 );
|
||||
em.persist( w );
|
||||
|
||||
w = new Widget();
|
||||
w.setCode( "AAA" );
|
||||
w.setDivision( "EU" );
|
||||
w.setCost( 12.50 );
|
||||
em.persist( w );
|
||||
|
||||
w = new Widget();
|
||||
w.setCode( "AAA" );
|
||||
w.setDivision( "ASIA" );
|
||||
w.setCost( 110.00 );
|
||||
em.persist( w );
|
||||
|
||||
w = new Widget();
|
||||
w.setCode( "BBB" );
|
||||
w.setDivision( "NA" );
|
||||
w.setCost( 14.00 );
|
||||
em.persist( w );
|
||||
|
||||
w = new Widget();
|
||||
w.setCode( "BBB" );
|
||||
w.setDivision( "EU" );
|
||||
w.setCost( 8.75 );
|
||||
em.persist( w );
|
||||
|
||||
w = new Widget();
|
||||
w.setCode( "BBB" );
|
||||
w.setDivision( "ASIA" );
|
||||
w.setCost( 86.22 );
|
||||
em.persist( w );
|
||||
|
||||
Tool t = new Tool();
|
||||
t.setName( "AAA" );
|
||||
t.setType( "NA" );
|
||||
t.setCost( 10.00 );
|
||||
em.persist( t );
|
||||
|
||||
t = new Tool();
|
||||
t.setName( "AAA" );
|
||||
t.setType( "EU" );
|
||||
t.setCost( 12.50 );
|
||||
em.persist( t );
|
||||
|
||||
t = new Tool();
|
||||
t.setName( "AAA" );
|
||||
t.setType( "ASIA" );
|
||||
t.setCost( 110.00 );
|
||||
em.persist( t );
|
||||
|
||||
t = new Tool();
|
||||
t.setName( "BBB" );
|
||||
t.setType( "NA" );
|
||||
t.setCost( 14.00 );
|
||||
em.persist( t );
|
||||
|
||||
t = new Tool();
|
||||
t.setName( "BBB" );
|
||||
t.setType( "EU" );
|
||||
t.setCost( 8.75 );
|
||||
em.persist( t );
|
||||
|
||||
t = new Tool();
|
||||
t.setName( "BBB" );
|
||||
t.setType( "ASIA" );
|
||||
t.setCost( 86.22 );
|
||||
em.persist( t );
|
||||
|
||||
em.getTransaction().commit();
|
||||
em.close();
|
||||
}
|
||||
|
||||
|
||||
@After
|
||||
public void cleanupTestData() {
|
||||
EntityManager em = getOrCreateEntityManager();
|
||||
em.getTransaction().begin();
|
||||
em.createQuery( "delete Widget" ).executeUpdate();
|
||||
em.createQuery( "delete Tool" ).executeUpdate();
|
||||
em.getTransaction().commit();
|
||||
em.close();
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testDeclaredIdClassAttributes( ) {
|
||||
EntityManager em = getOrCreateEntityManager();
|
||||
em.getTransaction().begin();
|
||||
|
||||
// Packaging arguments for use in query.
|
||||
List<String> divisions = new ArrayList<String>( );
|
||||
divisions.add( "NA" );
|
||||
divisions.add( "EU" );
|
||||
|
||||
// Building the query.
|
||||
CriteriaBuilder criteria = em.getCriteriaBuilder( );
|
||||
CriteriaQuery<Widget> query = criteria.createQuery( Widget.class );
|
||||
Root<Widget> root = query.from( Widget.class );
|
||||
|
||||
Predicate predicate = root.get( "division" ).in( divisions );
|
||||
query.where( predicate );
|
||||
|
||||
// Retrieving query.;
|
||||
List<Widget> widgets = em.createQuery( query ).getResultList( );
|
||||
Assert.assertEquals( 4, widgets.size() );
|
||||
|
||||
em.getTransaction().commit();
|
||||
em.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSupertypeIdClassAttributes( ) {
|
||||
EntityManager em = getOrCreateEntityManager();
|
||||
em.getTransaction().begin();
|
||||
|
||||
// Packaging arguments for use in query.
|
||||
List<String> types = new ArrayList<String>( );
|
||||
types.add( "NA" );
|
||||
types.add( "EU" );
|
||||
|
||||
// Building the query.
|
||||
CriteriaBuilder criteria = em.getCriteriaBuilder( );
|
||||
CriteriaQuery<Tool> query = criteria.createQuery( Tool.class );
|
||||
Root<Tool> root = query.from( Tool.class );
|
||||
|
||||
Predicate predicate = root.get( "type" ).in( types );
|
||||
query.where( predicate );
|
||||
|
||||
// Retrieving query.
|
||||
List<Tool> tools = em.createQuery( query ).getResultList( );
|
||||
Assert.assertEquals( 4, tools.size() );
|
||||
|
||||
em.getTransaction().commit();
|
||||
em.close();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2011, 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.ejb.criteria.idclass;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.IdClass;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Table;
|
||||
|
||||
/**
|
||||
* @author Gail Badner
|
||||
*/
|
||||
@Entity
|
||||
@Table( name = "TOOL" )
|
||||
public class Tool extends Helper {
|
||||
@Column( name = "COST" )
|
||||
private Double cost;
|
||||
public Double getCost( ) { return this.cost; }
|
||||
public void setCost( Double value ) { this.cost = value; }
|
||||
|
||||
@Override
|
||||
public String toString( ) {
|
||||
return "[" + super.toString() + "; Cost: " + this.getCost( ) + "]";
|
||||
}
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2011, 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.ejb.criteria.idclass;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.IdClass;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Table;
|
||||
|
||||
/**
|
||||
* @author Erich Heard
|
||||
*/
|
||||
@Entity
|
||||
@Table( name = "WIDGET" )
|
||||
@IdClass( org.hibernate.ejb.criteria.idclass.WidgetId.class )
|
||||
public class Widget {
|
||||
@Id
|
||||
private String code;
|
||||
public String getCode( ) { return this.code; }
|
||||
public void setCode( String value ) { this.code = value; }
|
||||
|
||||
@Id
|
||||
private String division;
|
||||
public String getDivision( ) { return this.division; }
|
||||
public void setDivision( String value ) { this.division = value; }
|
||||
|
||||
@Column( name = "COST" )
|
||||
private Double cost;
|
||||
public Double getCost( ) { return this.cost; }
|
||||
public void setCost( Double value ) { this.cost = value; }
|
||||
|
||||
@Override
|
||||
public String toString( ) {
|
||||
return "[Code:" + this.getCode( ) + "; Division: " + this.getDivision( ) + "; Cost: " + this.getCost( ) + "]";
|
||||
}
|
||||
}
|
|
@ -0,0 +1,77 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2011, 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.ejb.criteria.idclass;
|
||||
|
||||
import java.io.Serializable;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Embeddable;
|
||||
import javax.persistence.Id;
|
||||
|
||||
/**
|
||||
* @author Erich Heard
|
||||
*/
|
||||
|
||||
@Embeddable
|
||||
public class WidgetId implements Serializable {
|
||||
private static final long serialVersionUID = 9122480802791185644L;
|
||||
|
||||
@Id
|
||||
@Column( name = "CODE", length = 3 )
|
||||
private String code;
|
||||
public String getCode( ) { return this.code; }
|
||||
public void setCode( String value ) { this.code = value; }
|
||||
|
||||
@Id
|
||||
@Column( name = "DIVISION", length = 4 )
|
||||
private String division;
|
||||
public String getDivision( ) { return this.division; }
|
||||
public void setDivision( String value ) { this.division = value; }
|
||||
|
||||
@Override
|
||||
public boolean equals( Object obj ) {
|
||||
if( obj == null ) return false;
|
||||
if( !( obj instanceof WidgetId ) ) return false;
|
||||
|
||||
WidgetId id = ( WidgetId )obj;
|
||||
if( this.getCode( ) == null || id.getCode( ) == null || this.getDivision( ) == null || id.getDivision( ) == null ) return false;
|
||||
|
||||
return this.toString( ).equals( id.toString( ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode( ) {
|
||||
return this.toString( ).hashCode( );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString( ) {
|
||||
StringBuffer buf = new StringBuffer( "[id:" );
|
||||
buf.append( ( this.getCode( ) == null ) ? "null" : this.getCode( ).toString( ) );
|
||||
buf.append( ";code:" );
|
||||
buf.append( ( this.getDivision( ) == null ) ? "null" : this.getDivision( ) );
|
||||
buf.append( "]" );
|
||||
|
||||
return buf.toString( );
|
||||
}
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2011 by Red Hat Inc and/or its affiliates or by
|
||||
* third-party contributors as indicated by either @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.ejb.test.metadata;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
|
||||
/**
|
||||
* @author Gail Badner
|
||||
*/
|
||||
@Entity(name="HomoGigantus")
|
||||
public class Giant extends Person {
|
||||
private long height;
|
||||
|
||||
public long getHeight() {
|
||||
return height;
|
||||
}
|
||||
|
||||
public void setHeight(long height) {
|
||||
this.height = height;
|
||||
}
|
||||
}
|
|
@ -49,6 +49,7 @@ import static org.junit.Assert.assertEquals;
|
|||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertSame;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
|
@ -133,6 +134,39 @@ public class MetadataTest extends BaseEntityManagerFunctionalTestCase {
|
|||
assertEquals( 2, ids.size() );
|
||||
for (SingularAttribute<? super Person,?> localId : ids) {
|
||||
assertTrue( localId.isId() );
|
||||
assertSame( personType, localId.getDeclaringType() );
|
||||
assertSame( localId, personType.getDeclaredAttribute( localId.getName() ) );
|
||||
assertSame( localId, personType.getDeclaredSingularAttribute( localId.getName() ) );
|
||||
assertSame( localId, personType.getAttribute( localId.getName() ) );
|
||||
assertSame( localId, personType.getSingularAttribute( localId.getName() ) );
|
||||
assertTrue( personType.getAttributes().contains( localId ) );
|
||||
}
|
||||
|
||||
final EntityType<Giant> giantType = entityManagerFactory().getMetamodel().entity( Giant.class );
|
||||
assertEquals( "HomoGigantus", giantType.getName() );
|
||||
assertFalse( giantType.hasSingleIdAttribute() );
|
||||
final Set<SingularAttribute<? super Giant,?>> giantIds = giantType.getIdClassAttributes();
|
||||
assertNotNull( giantIds );
|
||||
assertEquals( 2, giantIds.size() );
|
||||
assertEquals( personType.getIdClassAttributes(), giantIds );
|
||||
for (SingularAttribute<? super Giant,?> localGiantId : giantIds) {
|
||||
assertTrue( localGiantId.isId() );
|
||||
try {
|
||||
giantType.getDeclaredAttribute( localGiantId.getName() );
|
||||
fail( localGiantId.getName() + " is a declared attribute, but shouldn't be");
|
||||
}
|
||||
catch ( IllegalArgumentException ex) {
|
||||
// expected
|
||||
}
|
||||
try {
|
||||
giantType.getDeclaredSingularAttribute( localGiantId.getName() );
|
||||
fail( localGiantId.getName() + " is a declared singular attribute, but shouldn't be");
|
||||
}
|
||||
catch ( IllegalArgumentException ex) {
|
||||
// expected
|
||||
}
|
||||
assertSame( localGiantId, giantType.getAttribute( localGiantId.getName() ) );
|
||||
assertTrue( giantType.getAttributes().contains( localGiantId ) );
|
||||
}
|
||||
|
||||
final EntityType<FoodItem> foodType = entityManagerFactory().getMetamodel().entity( FoodItem.class );
|
||||
|
@ -369,6 +403,7 @@ public class MetadataTest extends BaseEntityManagerFunctionalTestCase {
|
|||
Fridge.class,
|
||||
FoodItem.class,
|
||||
Person.class,
|
||||
Giant.class,
|
||||
House.class,
|
||||
Dog.class,
|
||||
Cat.class,
|
||||
|
|
Loading…
Reference in New Issue