/* * Copyright 2011-2017 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.data.jpa.repository.support; import static org.hamcrest.Matchers.*; import static org.junit.Assert.*; import static org.springframework.data.jpa.repository.support.JpaEntityInformationSupport.*; import java.io.Serializable; import java.sql.Timestamp; import java.util.Date; import java.util.Optional; import javax.persistence.Access; import javax.persistence.AccessType; import javax.persistence.Entity; import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; import javax.persistence.Id; import javax.persistence.IdClass; import javax.persistence.MappedSuperclass; import javax.persistence.Persistence; import javax.persistence.PersistenceContext; import javax.persistence.metamodel.Metamodel; import org.hibernate.Version; import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.data.jpa.domain.AbstractPersistable; import org.springframework.data.jpa.domain.sample.ConcreteType1; import org.springframework.data.jpa.domain.sample.Item; import org.springframework.data.jpa.domain.sample.ItemId; import org.springframework.data.jpa.domain.sample.ItemSite; import org.springframework.data.jpa.domain.sample.ItemSiteId; import org.springframework.data.jpa.domain.sample.PersistableWithIdClass; import org.springframework.data.jpa.domain.sample.PersistableWithIdClassPK; import org.springframework.data.jpa.domain.sample.PrimitiveVersionProperty; import org.springframework.data.jpa.domain.sample.Role; import org.springframework.data.jpa.domain.sample.SampleWithIdClass; import org.springframework.data.jpa.domain.sample.SampleWithPrimitiveId; import org.springframework.data.jpa.domain.sample.SampleWithTimestampVersion; import org.springframework.data.jpa.domain.sample.Site; import org.springframework.data.jpa.domain.sample.User; import org.springframework.data.jpa.domain.sample.VersionedUser; import org.springframework.data.repository.core.EntityInformation; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.util.ReflectionTestUtils; /** * Integration tests for {@link JpaMetamodelEntityInformation}. * * @author Oliver Gierke * @author Thomas Darimont * @author Christoph Strobl */ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration({ "classpath:infrastructure.xml" }) public class JpaMetamodelEntityInformationIntegrationTests { @PersistenceContext EntityManager em; @Test public void detectsIdTypeForEntity() { JpaEntityInformation<User, ?> information = getEntityInformation(User.class, em); assertThat(information.getIdType(), is(typeCompatibleWith(Integer.class))); } /** * Ignored for Hibernate as it does not implement {@link Metamodel#managedType(Class)} correctly (does not consider * {@link MappedSuperclass}es correctly). * * @see <a href="https://hibernate.atlassian.net/browse/HHH-6896">HHH-6896</a> */ @Test // DATAJPA-141 @Ignore public void detectsIdTypeForMappedSuperclass() { JpaEntityInformation<?, ?> information = getEntityInformation(AbstractPersistable.class, em); assertEquals(Serializable.class, information.getIdType()); } @Test // DATAJPA-50 public void detectsIdClass() { EntityInformation<PersistableWithIdClass, ?> information = getEntityInformation(PersistableWithIdClass.class, em); assertThat(information.getIdType(), is(typeCompatibleWith(PersistableWithIdClassPK.class))); } @Test // DATAJPA-50 public void returnsIdOfPersistableInstanceCorrectly() { PersistableWithIdClass entity = new PersistableWithIdClass(2L, 4L); JpaEntityInformation<PersistableWithIdClass, ?> information = getEntityInformation(PersistableWithIdClass.class, em); Object id = information.getId(entity); assertThat(id, is(Optional.of(new PersistableWithIdClassPK(2L, 4L)))); } @Test // DATAJPA-413 public void returnsIdOfEntityWithIdClassCorrectly() { Item item = new Item(2, 1); JpaEntityInformation<Item, ?> information = getEntityInformation(Item.class, em); Object id = information.getId(item); assertThat(id, is(Optional.of(new ItemId(2, 1)))); } @Test // DATAJPA-413 public void returnsDerivedIdOfEntityWithIdClassCorrectly() { Item item = new Item(1, 2); Site site = new Site(3); ItemSite itemSite = new ItemSite(item, site); JpaEntityInformation<ItemSite, ?> information = getEntityInformation(ItemSite.class, em); Object id = information.getId(itemSite); assertThat(id, is(Optional.of(new ItemSiteId(new ItemId(1, 2), 3)))); } @Test // DATAJPA-413 public void returnsPartialEmptyDerivedIdOfEntityWithIdClassCorrectly() { Item item = new Item(1, null); Site site = new Site(3); ItemSite itemSite = new ItemSite(item, site); JpaEntityInformation<ItemSite, ?> information = getEntityInformation(ItemSite.class, em); Object id = information.getId(itemSite); assertThat(id, is(Optional.of(new ItemSiteId(new ItemId(1, null), 3)))); } @Test // DATAJPA-119 public void favoursVersionAnnotationIfPresent() { EntityInformation<VersionedUser, Long> information = new JpaMetamodelEntityInformation<VersionedUser, Long>( VersionedUser.class, em.getMetamodel()); VersionedUser entity = new VersionedUser(); assertThat(information.isNew(entity), is(true)); entity.setId(1L); assertThat(information.isNew(entity), is(true)); entity.setVersion(1L); assertThat(information.isNew(entity), is(false)); entity.setId(null); assertThat(information.isNew(entity), is(false)); } @Test // DATAJPA-348 public void findsIdClassOnMappedSuperclass() { EntityManagerFactory emf = Persistence.createEntityManagerFactory(getMetadadataPersitenceUnitName()); EntityManager em = emf.createEntityManager(); EntityInformation<Sample, BaseIdClass> information = new JpaMetamodelEntityInformation<Sample, BaseIdClass>( Sample.class, em.getMetamodel()); assertThat(information.getIdType(), is((Object) BaseIdClass.class)); } @Test // DATACMNS-357 public void detectsNewStateForEntityWithPrimitiveId() { EntityInformation<SampleWithPrimitiveId, Long> information = new JpaMetamodelEntityInformation<SampleWithPrimitiveId, Long>( SampleWithPrimitiveId.class, em.getMetamodel()); SampleWithPrimitiveId sample = new SampleWithPrimitiveId(); assertThat(information.isNew(sample), is(true)); sample.setId(5L); assertThat(information.isNew(sample), is(false)); } @Test // DATAJPA-509 public void jpaMetamodelEntityInformationShouldRespectExplicitlyConfiguredEntityNameFromOrmXml() { JpaEntityInformation<Role, Integer> info = new JpaMetamodelEntityInformation<Role, Integer>(Role.class, em.getMetamodel()); assertThat(info.getEntityName(), is("ROLE")); } @Test // DATAJPA-561 public void considersEntityWithPrimitiveVersionPropertySetToDefaultNew() { EntityInformation<PrimitiveVersionProperty, Serializable> information = new JpaMetamodelEntityInformation<PrimitiveVersionProperty, Serializable>( PrimitiveVersionProperty.class, em.getMetamodel()); assertThat(information.isNew(new PrimitiveVersionProperty()), is(true)); } @Test // DATAJPA-568 public void considersEntityAsNotNewWhenHavingIdSetAndUsingPrimitiveTypeForVersionProperty() { EntityInformation<PrimitiveVersionProperty, Serializable> information = new JpaMetamodelEntityInformation<PrimitiveVersionProperty, Serializable>( PrimitiveVersionProperty.class, em.getMetamodel()); PrimitiveVersionProperty pvp = new PrimitiveVersionProperty(); pvp.id = 100L; assertThat(information.isNew(pvp), is(false)); } @Test // DATAJPA-568 public void fallsBackToIdInspectionForAPrimitiveVersionProperty() { EntityInformation<PrimitiveVersionProperty, Serializable> information = new JpaMetamodelEntityInformation<PrimitiveVersionProperty, Serializable>( PrimitiveVersionProperty.class, em.getMetamodel()); PrimitiveVersionProperty pvp = new PrimitiveVersionProperty(); pvp.version = 1L; assertThat(information.isNew(pvp), is(true)); pvp.id = 1L; assertThat(information.isNew(pvp), is(false)); } @Test // DATAJPA-582 public void considersEntityWithUnsetCompundIdNew() { EntityInformation<SampleWithIdClass, ?> information = getEntityInformation(SampleWithIdClass.class, em); assertThat(information.isNew(new SampleWithIdClass()), is(true)); } @Test // DATAJPA-582 public void considersEntityWithSetTimestampVersionNotNew() { EntityInformation<SampleWithTimestampVersion, ?> information = getEntityInformation( SampleWithTimestampVersion.class, em); SampleWithTimestampVersion entity = new SampleWithTimestampVersion(); entity.version = new Timestamp(new Date().getTime()); assertThat(information.isNew(entity), is(false)); } @Test // DATAJPA-582, DATAJPA-581 public void considersEntityWithNonPrimitiveNonNullIdTypeNotNew() { EntityInformation<User, ?> information = getEntityInformation(User.class, em); User user = new User(); assertThat(information.isNew(user), is(true)); user.setId(0); assertThat(information.isNew(user), is(false)); } /** * Ignored as Hibernate < 4.3 doesn't expose the version property properly if it's declared on the superclass. */ @Test // DATAJPA-820 @Ignore public void detectsVersionPropertyOnMappedSuperClass() { EntityInformation<ConcreteType1, ?> information = getEntityInformation(ConcreteType1.class, em); assertThat(ReflectionTestUtils.getField(information, "versionAttribute"), is(notNullValue())); } protected String getMetadadataPersitenceUnitName() { return Version.getVersionString().startsWith("5.2") ? "metadata-52" : "metadata"; } @SuppressWarnings("serial") public static class BaseIdClass implements Serializable { Long id; Long feedRunId; } @MappedSuperclass @IdClass(BaseIdClass.class) @Access(AccessType.FIELD) public static abstract class Identifiable { @Id Long id; @Id Long feedRunId; } @Entity @Access(AccessType.FIELD) public static class Sample extends Identifiable { } }