diff --git a/hibernate-core/src/main/java/org/hibernate/mapping/Component.java b/hibernate-core/src/main/java/org/hibernate/mapping/Component.java index 4269417a5e2e..fd48b6156c13 100644 --- a/hibernate-core/src/main/java/org/hibernate/mapping/Component.java +++ b/hibernate-core/src/main/java/org/hibernate/mapping/Component.java @@ -42,6 +42,7 @@ import org.hibernate.property.Setter; import org.hibernate.tuple.component.ComponentMetamodel; import org.hibernate.type.Type; +import org.hibernate.type.TypeFactory; /** * The mapping for a component, composite element, @@ -166,25 +167,11 @@ public void setDynamic(boolean dynamic) { this.dynamic = dynamic; } - private Type type; - public Type getType() throws MappingException { - // added this caching as I noticed that getType() is being called multiple times... - if ( type == null ) { - type = buildType(); - } - return type; - } - - private Type buildType() { // TODO : temporary initial step towards HHH-1907 - ComponentMetamodel metamodel = new ComponentMetamodel( this ); - if ( isEmbedded() ) { - return getMappings().getTypeResolver().getTypeFactory().embeddedComponent( metamodel ); - } - else { - return getMappings().getTypeResolver().getTypeFactory().component( metamodel ); - } + final ComponentMetamodel metamodel = new ComponentMetamodel( this ); + final TypeFactory factory = getMappings().getTypeResolver().getTypeFactory(); + return isEmbedded() ? factory.embeddedComponent( metamodel ) : factory.component( metamodel ); } public void setTypeUsingReflection(String className, String propertyName) diff --git a/hibernate-core/src/main/java/org/hibernate/tuple/component/ComponentMetamodel.java b/hibernate-core/src/main/java/org/hibernate/tuple/component/ComponentMetamodel.java index 04ef3c233270..ae974156782b 100644 --- a/hibernate-core/src/main/java/org/hibernate/tuple/component/ComponentMetamodel.java +++ b/hibernate-core/src/main/java/org/hibernate/tuple/component/ComponentMetamodel.java @@ -77,12 +77,10 @@ public ComponentMetamodel(Component component) { // todo : move this to SF per HHH-3517; also see HHH-1907 and ComponentMetamodel final ComponentTuplizerFactory componentTuplizerFactory = new ComponentTuplizerFactory(); final String tuplizerClassName = component.getTuplizerImplClassName( entityMode ); - if ( tuplizerClassName == null ) { - componentTuplizer = componentTuplizerFactory.constructDefaultTuplizer( entityMode, component ); - } - else { - componentTuplizer = componentTuplizerFactory.constructTuplizer( tuplizerClassName, component ); - } + this.componentTuplizer = tuplizerClassName == null ? componentTuplizerFactory.constructDefaultTuplizer( + entityMode, + component + ) : componentTuplizerFactory.constructTuplizer( tuplizerClassName, component ); } public boolean isKey() { diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/embeddables/DollarValue.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/embeddables/DollarValue.java new file mode 100644 index 000000000000..d2ff6ef5e649 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/embeddables/DollarValue.java @@ -0,0 +1,47 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, 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.annotations.embeddables; + +import java.io.Serializable; +import java.math.BigDecimal; + +/** + * @author Chris Pheby + */ +public class DollarValue implements Serializable { + + private static final long serialVersionUID = -416056386419355705L; + + private BigDecimal amount; + + public DollarValue() {}; + + public DollarValue(BigDecimal amount) { + this.amount = amount; + } + + public BigDecimal getAmount() { + return amount; + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/embeddables/DollarValueUserType.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/embeddables/DollarValueUserType.java new file mode 100644 index 000000000000..d31dde62fc17 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/embeddables/DollarValueUserType.java @@ -0,0 +1,112 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, 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.annotations.embeddables; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Types; + +import org.hibernate.HibernateException; +import org.hibernate.engine.spi.SessionImplementor; +import org.hibernate.usertype.UserType; + +/** + * @author Chris Pheby + */ +public class DollarValueUserType implements UserType { + + @Override + public int[] sqlTypes() { + return new int[] {Types.BIGINT}; + } + + @Override + public Class returnedClass() { + return DollarValue.class; + } + + @Override + public boolean equals(Object x, Object y) throws HibernateException { + if (!(x instanceof DollarValue) || !(y instanceof DollarValue)) { + throw new HibernateException("Expected DollarValue"); + } + return ((DollarValue)x).getAmount().equals(((DollarValue)y).getAmount()); + } + + @Override + public int hashCode(Object x) throws HibernateException { + if (!(x instanceof DollarValue)) { + throw new HibernateException("Expected DollarValue"); + } + return ((DollarValue)x).getAmount().hashCode(); + } + + @Override + public DollarValue nullSafeGet(ResultSet rs, String[] names, + SessionImplementor session, Object owner) + throws HibernateException, SQLException { + + DollarValue result = new DollarValue(rs.getBigDecimal(rs.findColumn(names[0]))); + return result; + } + + @Override + public void nullSafeSet(PreparedStatement st, Object value, int index, + SessionImplementor session) throws HibernateException, SQLException { + + st.setBigDecimal(index, ((DollarValue)value).getAmount()); + } + + @Override + public Object deepCopy(Object value) throws HibernateException { + DollarValue result = new DollarValue(); + + return result; + } + + @Override + public boolean isMutable() { + return false; + } + + @Override + public Serializable disassemble(Object value) throws HibernateException { + return null; + } + + @Override + public Object assemble(Serializable cached, Object owner) + throws HibernateException { + return null; + } + + @Override + public Object replace(Object original, Object target, Object owner) + throws HibernateException { + return null; + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/embeddables/EmbeddableIntegratorTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/embeddables/EmbeddableIntegratorTest.java new file mode 100644 index 000000000000..8b71febc67f4 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/embeddables/EmbeddableIntegratorTest.java @@ -0,0 +1,126 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, 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.annotations.embeddables; + +import static org.junit.Assert.assertEquals; + +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.Date; +import java.util.LinkedHashSet; +import java.util.List; + +import org.hibernate.Session; +import org.hibernate.SessionFactory; +import org.hibernate.cfg.Configuration; +import org.hibernate.exception.GenericJDBCException; +import org.hibernate.integrator.internal.IntegratorServiceImpl; +import org.hibernate.integrator.spi.Integrator; +import org.hibernate.integrator.spi.IntegratorService; +import org.hibernate.service.ServiceRegistry; +import org.hibernate.service.ServiceRegistryBuilder; +import org.hibernate.service.classloading.internal.ClassLoaderServiceImpl; +import org.hibernate.service.classloading.spi.ClassLoaderService; +import org.hibernate.service.internal.BootstrapServiceRegistryImpl; +import org.hibernate.testing.junit4.BaseUnitTestCase; +import org.junit.Test; + +/** + * @author Chris Pheby + */ +public class EmbeddableIntegratorTest extends BaseUnitTestCase { + + /** + * Throws a mapping exception because DollarValue is not mapped + */ + @Test(expected=GenericJDBCException.class) + public void testWithoutIntegrator() { + + ServiceRegistry reg = new ServiceRegistryBuilder(new BootstrapServiceRegistryImpl()) + .buildServiceRegistry(); + + SessionFactory sf = new Configuration() + .addAnnotatedClass( Investor.class ) + + .buildSessionFactory(reg); + + Session sess = sf.openSession(); + Investor myInv = getInvestor(); + myInv.setId(1L); + + sess.save(myInv); + sess.flush(); + sess.clear(); + + Investor inv = (Investor) sess.get(Investor.class, 1L); + assertEquals(new BigDecimal("100"), inv.getInvestments().get(0).getAmount().getAmount()); + + sess.close(); + } + + @Test + public void testWithIntegrator() { + + LinkedHashSet providedIntegrators = new LinkedHashSet(); + providedIntegrators.add(new InvestorIntegrator()); + ClassLoaderService classLoaderService = new ClassLoaderServiceImpl(); + IntegratorService integratorService = new IntegratorServiceImpl(providedIntegrators, classLoaderService); + + ServiceRegistry reg = new ServiceRegistryBuilder(new BootstrapServiceRegistryImpl( + classLoaderService, + integratorService)).buildServiceRegistry(); + + SessionFactory sf = new Configuration() + .addAnnotatedClass( Investor.class ) + + .setProperty("hibernate.hbm2ddl.auto", "create-drop") + .buildSessionFactory(reg); + + Session sess = sf.openSession(); + Investor myInv = getInvestor(); + myInv.setId(2L); + + sess.save(myInv); + sess.flush(); + sess.clear(); + + Investor inv = (Investor) sess.get(Investor.class, 2L); + assertEquals(new BigDecimal("100"), inv.getInvestments().get(0).getAmount().getAmount()); + + sess.close(); + } + + private Investor getInvestor() { + Investor i = new Investor(); + List investments = new ArrayList(); + Investment i1 = new Investment(); + i1.setAmount(new DollarValue(new BigDecimal("100"))); + i1.setDate(new MyDate(new Date())); + i1.setDescription("Test Investment"); + investments.add(i1); + i.setInvestments(investments); + + return i; + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/embeddables/Investment.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/embeddables/Investment.java new file mode 100644 index 000000000000..db2f598c23f4 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/embeddables/Investment.java @@ -0,0 +1,63 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, 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.annotations.embeddables; + +import javax.persistence.Column; +import javax.persistence.Embeddable; + +/** + * @author Chris Pheby + */ +@Embeddable +public class Investment { + + private DollarValue amount; + private String description; + private MyDate date; + + public DollarValue getAmount() { + return amount; + } + + public void setAmount(DollarValue amount) { + this.amount = amount; + } + + @Column(length = 500) + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public MyDate getDate() { + return date; + } + + public void setDate(MyDate date) { + this.date = date; + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/embeddables/Investor.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/embeddables/Investor.java new file mode 100644 index 000000000000..d52c041fbcbe --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/embeddables/Investor.java @@ -0,0 +1,61 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, 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.annotations.embeddables; + +import java.util.ArrayList; +import java.util.List; + +import javax.persistence.ElementCollection; +import javax.persistence.Entity; +import javax.persistence.FetchType; +import javax.persistence.Id; + +/** + * @author Chris Pheby + */ +@Entity +public class Investor { + + private Long id; + + private List investments = new ArrayList(); + + @Id + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + @ElementCollection(fetch = FetchType.EAGER) + public List getInvestments() { + return investments; + } + + public void setInvestments(List investments) { + this.investments = investments; + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/embeddables/InvestorIntegrator.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/embeddables/InvestorIntegrator.java new file mode 100644 index 000000000000..651003e947a4 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/embeddables/InvestorIntegrator.java @@ -0,0 +1,57 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, 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.annotations.embeddables; + +import org.hibernate.cfg.Configuration; +import org.hibernate.engine.spi.SessionFactoryImplementor; +import org.hibernate.integrator.spi.Integrator; +import org.hibernate.metamodel.source.MetadataImplementor; +import org.hibernate.service.spi.SessionFactoryServiceRegistry; + +/** + * @author Chris Pheby + */ +public class InvestorIntegrator implements Integrator { + + @Override + public void integrate(Configuration configuration, + SessionFactoryImplementor sessionFactory, + SessionFactoryServiceRegistry serviceRegistry) { + configuration.registerTypeOverride(new DollarValueUserType(), new String[] {DollarValue.class.getName()}); + configuration.registerTypeOverride(new MyDateUserType(), new String[] {MyDate.class.getName()}); + } + + @Override + public void integrate(MetadataImplementor metadata, + SessionFactoryImplementor sessionFactory, + SessionFactoryServiceRegistry serviceRegistry) { + // No-op + } + + @Override + public void disintegrate(SessionFactoryImplementor sessionFactory, + SessionFactoryServiceRegistry serviceRegistry) { + } + +} diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/embeddables/MyDate.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/embeddables/MyDate.java new file mode 100644 index 000000000000..c4d77347b053 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/embeddables/MyDate.java @@ -0,0 +1,48 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, 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.annotations.embeddables; + +import java.io.Serializable; +import java.util.Date; + +/** + * @author Chris Pheby + */ +public class MyDate implements Serializable { + + private static final long serialVersionUID = -416056386419355705L; + + private Date date; + + public MyDate() { + } + + public MyDate(Date date) { + this.date = date; + } + + public Date getDate() { + return date; + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/embeddables/MyDateUserType.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/embeddables/MyDateUserType.java new file mode 100644 index 000000000000..faff9d2f8e07 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/embeddables/MyDateUserType.java @@ -0,0 +1,111 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, 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.annotations.embeddables; + +import java.io.Serializable; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Types; + +import org.hibernate.HibernateException; +import org.hibernate.engine.spi.SessionImplementor; +import org.hibernate.usertype.UserType; + +/** + * @author Chris Pheby + */ +public class MyDateUserType implements UserType { + + @Override + public int[] sqlTypes() { + return new int[] {Types.DATE}; + } + + @Override + public Class returnedClass() { + return MyDate.class; + } + + @Override + public boolean equals(Object x, Object y) throws HibernateException { + if (!(x instanceof MyDate) || !(y instanceof MyDate)) { + throw new HibernateException("Expected MyDate"); + } + return ((MyDate)x).getDate().equals(((MyDate)y).getDate()); + } + + @Override + public int hashCode(Object x) throws HibernateException { + if (!(x instanceof MyDate)) { + throw new HibernateException("Expected MyDate"); + } + return ((MyDate)x).getDate().hashCode(); + } + + @Override + public MyDate nullSafeGet(ResultSet rs, String[] names, + SessionImplementor session, Object owner) + throws HibernateException, SQLException { + + MyDate result = new MyDate(rs.getDate(rs.findColumn(names[0]))); + return result; + } + + @Override + public void nullSafeSet(PreparedStatement st, Object value, int index, + SessionImplementor session) throws HibernateException, SQLException { + + st.setDate(index, new java.sql.Date(((MyDate)value).getDate().getTime())); + } + + @Override + public Object deepCopy(Object value) throws HibernateException { + MyDate result = new MyDate(); + + return result; + } + + @Override + public boolean isMutable() { + return false; + } + + @Override + public Serializable disassemble(Object value) throws HibernateException { + return null; + } + + @Override + public Object assemble(Serializable cached, Object owner) + throws HibernateException { + return null; + } + + @Override + public Object replace(Object original, Object target, Object owner) + throws HibernateException { + return null; + } +}