/* * 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.metamodel.source.annotations.entity; import javax.persistence.AttributeOverride; import javax.persistence.AttributeOverrides; import javax.persistence.Column; import javax.persistence.Embeddable; import javax.persistence.Embedded; import javax.persistence.Entity; import javax.persistence.Id; import org.junit.Test; import org.hibernate.annotations.Parent; import org.hibernate.annotations.Target; import org.hibernate.metamodel.binding.BasicAttributeBinding; import org.hibernate.metamodel.binding.ComponentAttributeBinding; import org.hibernate.metamodel.binding.EntityBinding; import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertNotNull; import static junit.framework.Assert.assertTrue; /** * Tests for {@code javax.persistence.Embeddable}. * * @author Hardy Ferentschik */ public class EmbeddableBindingTest extends BaseAnnotationBindingTestCase { @Entity class User { @Id private int id; @Embedded private Phone phone; } @Embeddable class Phone { String countryCode; String areaCode; String number; } @Test @Resources(annotatedClasses = { User.class, Phone.class }) public void testEmbeddable() { EntityBinding binding = getEntityBinding( User.class ); final String componentName = "phone"; assertNotNull( binding.locateAttributeBinding( componentName ) ); assertTrue( binding.locateAttributeBinding( componentName ) instanceof ComponentAttributeBinding ); ComponentAttributeBinding componentBinding = (ComponentAttributeBinding) binding.locateAttributeBinding( componentName ); // todo - is this really correct? Does the path start w/ the class name assertEquals( "Wrong path", "org.hibernate.metamodel.source.annotations.entity.EmbeddableBindingTest$User.phone", componentBinding.getPathBase() ); assertNotNull( componentBinding.locateAttributeBinding( "countryCode" ) ); assertNotNull( componentBinding.locateAttributeBinding( "areaCode" ) ); assertNotNull( componentBinding.locateAttributeBinding( "number" ) ); } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @Entity @AttributeOverride(name = "embedded.name", column = @Column(name = "FUBAR", length = 42)) class BaseEntity { @Id private int id; @Embedded private EmbeddedEntity embedded; } @Embeddable class EmbeddedEntity { String name; } @Test @Resources(annotatedClasses = { BaseEntity.class, EmbeddedEntity.class }) public void testEmbeddableWithAttributeOverride() { EntityBinding binding = getEntityBinding( BaseEntity.class ); final String componentName = "embedded"; assertNotNull( binding.locateAttributeBinding( componentName ) ); assertTrue( binding.locateAttributeBinding( componentName ) instanceof ComponentAttributeBinding ); ComponentAttributeBinding componentBinding = (ComponentAttributeBinding) binding.locateAttributeBinding( componentName ); assertNotNull( componentBinding.locateAttributeBinding( "name" ) ); BasicAttributeBinding nameAttribute = (BasicAttributeBinding) componentBinding.locateAttributeBinding( "name" ); org.hibernate.metamodel.relational.Column column = (org.hibernate.metamodel.relational.Column) nameAttribute.getValue(); assertEquals( "Attribute override specifies a custom column name", "FUBAR", column.getColumnName().getName() ); assertEquals( "Attribute override specifies a custom size", 42, column.getSize().getLength() ); } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @Embeddable public class Address { protected String street; protected String city; protected String state; @Embedded protected Zipcode zipcode; } @Embeddable public class Zipcode { protected String zip; protected String plusFour; } @Entity public class Customer { @Id protected Integer id; protected String name; @AttributeOverrides( { @AttributeOverride(name = "state", column = @Column(name = "ADDR_STATE")), @AttributeOverride(name = "zipcode.zip", column = @Column(name = "ADDR_ZIP")) }) @Embedded protected Address address; } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @Test @Resources(annotatedClasses = { Zipcode.class, Address.class, Customer.class }) public void testNestedEmbeddable() { EntityBinding binding = getEntityBinding( Customer.class ); final String addressComponentName = "address"; assertNotNull( binding.locateAttributeBinding( addressComponentName ) ); assertTrue( binding.locateAttributeBinding( addressComponentName ) instanceof ComponentAttributeBinding ); ComponentAttributeBinding attributeComponentBinding = (ComponentAttributeBinding) binding.locateAttributeBinding( addressComponentName ); assertNotNull( attributeComponentBinding.locateAttributeBinding( "street" ) ); assertNotNull( attributeComponentBinding.locateAttributeBinding( "city" ) ); assertNotNull( attributeComponentBinding.locateAttributeBinding( "state" ) ); BasicAttributeBinding stateAttribute = (BasicAttributeBinding) attributeComponentBinding.locateAttributeBinding( "state" ); org.hibernate.metamodel.relational.Column column = (org.hibernate.metamodel.relational.Column) stateAttribute.getValue(); assertEquals( "Attribute override specifies a custom column name", "ADDR_STATE", column.getColumnName().getName() ); final String zipComponentName = "zipcode"; assertNotNull( attributeComponentBinding.locateAttributeBinding( zipComponentName ) ); assertTrue( attributeComponentBinding.locateAttributeBinding( zipComponentName ) instanceof ComponentAttributeBinding ); ComponentAttributeBinding zipComponentBinding = (ComponentAttributeBinding) attributeComponentBinding.locateAttributeBinding( zipComponentName ); BasicAttributeBinding nameAttribute = (BasicAttributeBinding) zipComponentBinding.locateAttributeBinding( "zip" ); column = (org.hibernate.metamodel.relational.Column) nameAttribute.getValue(); assertEquals( "Attribute override specifies a custom column name", "ADDR_ZIP", column.getColumnName().getName() ); } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @Embeddable public class A { @Embedded @AttributeOverrides( { @AttributeOverride(name = "foo", column = @Column(name = "BAR")), @AttributeOverride(name = "fubar", column = @Column(name = "A_WINS")) }) private B b; public B getB() { return b; } } @Embeddable public class B { private String foo; private String fubar; public String getFoo() { return foo; } public String getFubar() { return fubar; } } @Entity public class C { @Id int id; @Embedded @AttributeOverride(name = "b.fubar", column = @Column(name = "C_WINS")) protected A a; public int getId() { return id; } public A getA() { return a; } } @Test @Resources(annotatedClasses = { A.class, B.class, C.class }) public void testAttributeOverrideInEmbeddable() { EntityBinding binding = getEntityBinding( C.class ); final String aComponentName = "a"; assertNotNull( binding.locateAttributeBinding( aComponentName ) ); assertTrue( binding.locateAttributeBinding( aComponentName ) instanceof ComponentAttributeBinding ); ComponentAttributeBinding aComponentBinding = (ComponentAttributeBinding) binding.locateAttributeBinding( aComponentName ); final String bComponentName = "b"; assertNotNull( aComponentBinding.locateAttributeBinding( bComponentName ) ); assertTrue( aComponentBinding.locateAttributeBinding( bComponentName ) instanceof ComponentAttributeBinding ); ComponentAttributeBinding bComponentBinding = (ComponentAttributeBinding) aComponentBinding.locateAttributeBinding( bComponentName ); BasicAttributeBinding attribute = (BasicAttributeBinding) bComponentBinding.locateAttributeBinding( "foo" ); org.hibernate.metamodel.relational.Column column = (org.hibernate.metamodel.relational.Column) attribute.getValue(); assertEquals( "Attribute override specifies a custom column name", "BAR", column.getColumnName().getName() ); attribute = (BasicAttributeBinding) bComponentBinding.locateAttributeBinding( "fubar" ); column = (org.hibernate.metamodel.relational.Column) attribute.getValue(); assertEquals( "Attribute override specifies a custom column name", "C_WINS", column.getColumnName().getName() ); } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @Embeddable public class EmbeddableEntity { private String test; @Parent private MainEntity parent; } @Entity public class MainEntity { @Id private int id; @Embedded private EmbeddableEntity embedded; } @Test @Resources(annotatedClasses = { MainEntity.class, EmbeddableEntity.class }) public void testParentReferencingAttributeName() { EntityBinding binding = getEntityBinding( MainEntity.class ); final String componentName = "embedded"; assertNotNull( binding.locateAttributeBinding( componentName ) ); assertTrue( binding.locateAttributeBinding( componentName ) instanceof ComponentAttributeBinding ); ComponentAttributeBinding componentBinding = (ComponentAttributeBinding) binding.locateAttributeBinding( componentName ); assertEquals( "Wrong parent reference name", "parent", componentBinding.getParentReference().getName() ); } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public interface Car { int getHorsePower(); } @Embeddable public class CarImpl implements Car { @Override public int getHorsePower() { return 0; } } @Entity public class Owner { private int id; private Car car; @Id public int getId() { return id; } @Embedded @Target(CarImpl.class) public Car getCar() { return car; } } @Test @Resources(annotatedClasses = { Owner.class, CarImpl.class, Car.class }) public void testTargetAnnotationWithEmbeddable() { EntityBinding binding = getEntityBinding( Owner.class ); final String componentName = "car"; assertNotNull( binding.locateAttributeBinding( componentName ) ); assertTrue( binding.locateAttributeBinding( componentName ) instanceof ComponentAttributeBinding ); ComponentAttributeBinding componentBinding = (ComponentAttributeBinding) binding.locateAttributeBinding( componentName ); BasicAttributeBinding attribute = (BasicAttributeBinding) componentBinding.locateAttributeBinding( "horsePower" ); assertTrue( attribute.getAttribute().isTypeResolved() ); assertEquals( "Wrong resolved type", "int", attribute.getAttribute().getSingularAttributeType().getClassName() ); } }