DATAJPA-413 - Guard identifier derivation against null values and add tests.

Added guard against null values in identifiers. Null values can occur because id generation was not completed yet. Add tests for identifier derivation using @IdClass for Hibernate, OpenJPA and EclipseLink.

Original pull request: #133.
This commit is contained in:
Mark Paluch
2016-07-18 11:51:46 +02:00
committed by Oliver Gierke
parent 0889315e0d
commit 6635836324
15 changed files with 614 additions and 9 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2011-2015 the original author or authors.
* Copyright 2011-2016 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.
@@ -45,6 +45,7 @@ import org.springframework.util.ClassUtils;
* @author Oliver Gierke
* @author Thomas Darimont
* @author Christoph Strobl
* @author Mark Paluch
*/
public class JpaMetamodelEntityInformation<T, ID extends Serializable> extends JpaEntityInformationSupport<T, ID> {
@@ -297,7 +298,7 @@ public class JpaMetamodelEntityInformation<T, ID extends Serializable> extends J
}
/**
* Custom extension of {@link DirectFieldAccessFallbackBeanWrapper} that allows to derived the identifier if composite
* Custom extension of {@link DirectFieldAccessFallbackBeanWrapper} that allows to derive the identifier if composite
* keys with complex key attribute types (e.g. types that are annotated with {@code @Entity} themselves) are used.
*
* @author Thomas Darimont
@@ -358,14 +359,19 @@ public class JpaMetamodelEntityInformation<T, ID extends Serializable> extends J
Object idPropertyValue = sourceIdValueWrapper.getPropertyValue(idAttributeName);
Class<? extends Object> idPropertyValueType = idPropertyValue.getClass();
if (idPropertyValue != null) {
if (ClassUtils.isPrimitiveOrWrapper(idPropertyValueType)) {
return idPropertyValue;
Class<? extends Object> idPropertyValueType = idPropertyValue.getClass();
if (ClassUtils.isPrimitiveOrWrapper(idPropertyValueType)) {
return idPropertyValue;
}
return new DirectFieldAccessFallbackBeanWrapper(idPropertyValue)
.getPropertyValue(tryFindSingularIdAttributeNameOrUseFallback(idPropertyValueType, idAttributeName));
}
return new DirectFieldAccessFallbackBeanWrapper(idPropertyValue)
.getPropertyValue(tryFindSingularIdAttributeNameOrUseFallback(idPropertyValueType, idAttributeName));
return null;
}
private String tryFindSingularIdAttributeNameOrUseFallback(Class<? extends Object> idPropertyValueType,

View File

@@ -0,0 +1,61 @@
/*
* Copyright 2016 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.domain.sample;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.IdClass;
import javax.persistence.JoinColumn;
import javax.persistence.Table;
/**
* @author Mark Paluch
* @see DATAJPA-413
* @see Final JPA 2.1 Specification 2.4.1.3 Derived Identities Example 2
*/
@Entity
@Table
@IdClass(ItemId.class)
public class Item {
@Id @Column(columnDefinition = "INT") Integer id;
@Id @JoinColumn(name = "manufacturer_id", columnDefinition = "INT") Integer manufacturerId;
public Item() {}
public Item(Integer id, Integer manufacturerId) {
this.id = id;
this.manufacturerId = manufacturerId;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public Integer getManufacturerId() {
return manufacturerId;
}
public void setManufacturerId(Integer manufacturerId) {
this.manufacturerId = manufacturerId;
}
}

View File

@@ -0,0 +1,75 @@
/*
* Copyright 2016 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.domain.sample;
import java.io.Serializable;
/**
* @author Mark Paluch
* @see DATAJPA-413
* @see Final JPA 2.1 Specification 2.4.1.3 Derived Identities Example 2
*/
public class ItemId implements Serializable {
private static final long serialVersionUID = -2986871112875450036L;
Integer id;
Integer manufacturerId;
public ItemId() {}
public ItemId(Integer id, Integer manufacturerId) {
this.id = id;
this.manufacturerId = manufacturerId;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public Integer getManufacturerId() {
return manufacturerId;
}
public void setManufacturerId(Integer manufacturerId) {
this.manufacturerId = manufacturerId;
}
@Override
public boolean equals(Object o) {
if (this == o)
return true;
if (!(o instanceof ItemId))
return false;
ItemId itemId = (ItemId) o;
if (id != null ? !id.equals(itemId.id) : itemId.id != null)
return false;
return manufacturerId != null ? manufacturerId.equals(itemId.manufacturerId) : itemId.manufacturerId == null;
}
@Override
public int hashCode() {
int result = id != null ? id.hashCode() : 0;
result = 31 * result + (manufacturerId != null ? manufacturerId.hashCode() : 0);
return result;
}
}

View File

@@ -0,0 +1,60 @@
/*
* Copyright 2016 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.domain.sample;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.IdClass;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
/**
* @author Mark Paluch
* @see DATAJPA-413
* @see Final JPA 2.1 Specification 2.4.1.3 Derived Identities Example 2
*/
@Entity
@Table
@IdClass(ItemSiteId.class)
public class ItemSite {
@Id @ManyToOne Item item;
@Id @ManyToOne Site site;
public ItemSite() {}
public ItemSite(Item item, Site site) {
this.item = item;
this.site = site;
}
public Item getItem() {
return item;
}
public void setItem(Item item) {
this.item = item;
}
public Site getSite() {
return site;
}
public void setSite(Site site) {
this.site = site;
}
}

View File

@@ -0,0 +1,59 @@
/*
* Copyright 2016 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.domain.sample;
import java.io.Serializable;
/**
* @author Mark Paluch
* @see DATAJPA-413
* @see Final JPA 2.1 Specification 2.4.1.3 Derived Identities Example 2
*/
public class ItemSiteId implements Serializable {
private static final long serialVersionUID = 1822540289216799357L;
ItemId item;
Integer site;
public ItemSiteId() {}
public ItemSiteId(ItemId item, Integer site) {
this.item = item;
this.site = site;
}
@Override
public boolean equals(Object o) {
if (this == o)
return true;
if (!(o instanceof ItemSiteId))
return false;
ItemSiteId that = (ItemSiteId) o;
if (item != null ? !item.equals(that.item) : that.item != null)
return false;
return site != null ? site.equals(that.site) : that.site == null;
}
@Override
public int hashCode() {
int result = item != null ? item.hashCode() : 0;
result = 31 * result + (site != null ? site.hashCode() : 0);
return result;
}
}

View File

@@ -0,0 +1,47 @@
/*
* Copyright 2016 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.domain.sample;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;
/**
* @author Mark Paluch
* @see DATAJPA-413
* @see Final JPA 2.1 Specification 2.4.1.3 Derived Identities Example 2
*/
@Entity
@Table
public class Site implements java.io.Serializable {
@Id @GeneratedValue Integer id;
public Site() {}
public Site(Integer id) {
this.id = id;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
}

View File

@@ -0,0 +1,31 @@
/*
* Copyright 2016 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;
import org.springframework.context.annotation.ImportResource;
import org.springframework.test.context.ContextConfiguration;
/**
* Testcase to run {@link RepositoryWithIdClassKeyTests} integration tests on top of EclipseLink.
*
* @author Mark Paluch
*/
@ContextConfiguration
public class EclipseLinkRepositoryWithCompositeKeyIntegrationTests extends RepositoryWithIdClassKeyTests {
@ImportResource({ "classpath:infrastructure.xml", "classpath:eclipselink.xml" })
static class TestConfig extends Config {}
}

View File

@@ -0,0 +1,33 @@
/*
* Copyright 2016 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;
import org.springframework.context.annotation.ImportResource;
import org.springframework.test.context.ContextConfiguration;
/**
* Testcase to run {@link RepositoryWithIdClassKeyTests} integration tests on top of OpenJPA.
*
* @author Mark Paluch
*/
@ContextConfiguration
public class OpenJpaRepositoryWithCompositeKeyIntegrationTests extends RepositoryWithIdClassKeyTests {
@ImportResource({ "classpath:infrastructure.xml", "classpath:openjpa.xml" })
static class TestConfig extends Config {
}
}

View File

@@ -0,0 +1,88 @@
/*
* Copyright 2016 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;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ImportResource;
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.Site;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.data.jpa.repository.sample.ItemRepository;
import org.springframework.data.jpa.repository.sample.ItemSiteRepository;
import org.springframework.data.jpa.repository.sample.SampleConfig;
import org.springframework.data.jpa.repository.sample.SiteRepository;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.transaction.annotation.Transactional;
/**
* Integration tests for Repositories using {@link javax.persistence.IdClass} identifiers.
*
* @author Mark Paluch
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = RepositoryWithIdClassKeyTests.TestConfig.class)
@Transactional
public class RepositoryWithIdClassKeyTests {
@Rule public ExpectedException expectedException = ExpectedException.none();
@Autowired private SiteRepository siteRepository;
@Autowired private ItemRepository itemRepository;
@Autowired private ItemSiteRepository itemSiteRepository;
@Configuration
@EnableJpaRepositories(basePackageClasses = SampleConfig.class)
static abstract class Config {
}
@ImportResource("classpath:infrastructure.xml")
static class TestConfig extends Config {
}
/**
* @see DATAJPA-413
* @see Final JPA 2.1 Specification 2.4.1.3 Derived Identities Example 2
*/
@Test
public void shouldSaveAndLoadEntitiesWithDerivedIdentities() throws Exception {
Site site = siteRepository.save(new Site());
Item item = itemRepository.save(new Item(123, 456));
itemSiteRepository.save(new ItemSite(item, site));
ItemSite loaded = itemSiteRepository
.findOne(new ItemSiteId(new ItemId(item.getId(), item.getManufacturerId()), site.getId()));
assertThat(loaded, is(notNullValue()));
}
}

View File

@@ -0,0 +1,27 @@
/*
* Copyright 2016 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.sample;
import org.springframework.data.jpa.domain.sample.Item;
import org.springframework.data.jpa.domain.sample.ItemId;
import org.springframework.data.jpa.repository.JpaRepository;
/**
* @author Mark Paluch
* @see DATAJPA-413
* @see Final JPA 2.1 Specification 2.4.1.3 Derived Identities Example 2
*/
public interface ItemRepository extends JpaRepository<Item, ItemId> {}

View File

@@ -0,0 +1,27 @@
/*
* Copyright 2016 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.sample;
import org.springframework.data.jpa.domain.sample.ItemSite;
import org.springframework.data.jpa.domain.sample.ItemSiteId;
import org.springframework.data.jpa.repository.JpaRepository;
/**
* @author Mark Paluch
* @see DATAJPA-413
* @see Final JPA 2.1 Specification 2.4.1.3 Derived Identities Example 2
*/
public interface ItemSiteRepository extends JpaRepository<ItemSite, ItemSiteId> {}

View File

@@ -0,0 +1,26 @@
/*
* Copyright 2016 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.sample;
import org.springframework.data.jpa.domain.sample.Site;
import org.springframework.data.jpa.repository.JpaRepository;
/**
* @author Mark Paluch
* @see DATAJPA-413
* @see Final JPA 2.1 Specification 2.4.1.3 Derived Identities Example 2
*/
public interface SiteRepository extends JpaRepository<Site, Integer> {}

View File

@@ -40,6 +40,10 @@ 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;
@@ -47,6 +51,7 @@ 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;
@@ -103,7 +108,7 @@ public class JpaMetamodelEntityInformationIntegrationTests {
* @see DATAJPA-50
*/
@Test
public void returnsIdInstanceCorrectly() {
public void returnsIdOfPersistableInstanceCorrectly() {
PersistableWithIdClass entity = new PersistableWithIdClass(2L, 4L);
@@ -115,6 +120,57 @@ public class JpaMetamodelEntityInformationIntegrationTests {
assertThat(id, is((Object) new PersistableWithIdClassPK(2L, 4L)));
}
/**
* @see DATAJPA-413
*/
@Test
public void returnsIdOfEntityWithIdClassCorrectly() {
Item item = new Item(2, 1);
JpaEntityInformation<Item, ?> information = getEntityInformation(Item.class, em);
Object id = information.getId(item);
assertThat(id, is(instanceOf(ItemId.class)));
assertThat(id, is((Object) new ItemId(2, 1)));
}
/**
* @see DATAJPA-413
*/
@Test
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(instanceOf(ItemSiteId.class)));
assertThat(id, is((Object) new ItemSiteId(new ItemId(1, 2), 3)));
}
/**
* @see DATAJPA-413
*/
@Test
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(instanceOf(ItemSiteId.class)));
assertThat(id, is((Object) new ItemSiteId(new ItemId(1, null), 3)));
}
/**
* @see DATAJPA-119
*/

View File

@@ -21,6 +21,8 @@
<class>org.springframework.data.jpa.domain.sample.EmbeddedIdExampleDepartment</class>
<class>org.springframework.data.jpa.domain.sample.IdClassExampleEmployee</class>
<class>org.springframework.data.jpa.domain.sample.IdClassExampleDepartment</class>
<class>org.springframework.data.jpa.domain.sample.Item</class>
<class>org.springframework.data.jpa.domain.sample.ItemSite</class>
<class>org.springframework.data.jpa.domain.sample.MailMessage</class>
<class>org.springframework.data.jpa.domain.sample.MailSender</class>
<class>org.springframework.data.jpa.domain.sample.MailUser</class>
@@ -35,6 +37,7 @@
<class>org.springframework.data.jpa.domain.sample.SampleWithIdClass</class>
<class>org.springframework.data.jpa.domain.sample.SampleWithPrimitiveId</class>
<class>org.springframework.data.jpa.domain.sample.SampleWithTimestampVersion</class>
<class>org.springframework.data.jpa.domain.sample.Site</class>
<class>org.springframework.data.jpa.domain.sample.SpecialUser</class>
<class>org.springframework.data.jpa.domain.sample.User</class>
<class>org.springframework.data.jpa.domain.sample.VersionedUser</class>

View File

@@ -7,12 +7,15 @@
<class>org.springframework.data.jpa.domain.sample.AuditableRole</class>
<class>org.springframework.data.jpa.domain.sample.AuditableUser</class>
<class>org.springframework.data.jpa.domain.sample.Category</class>
<class>org.springframework.data.jpa.domain.sample.CustomAbstractPersistable</class>
<class>org.springframework.data.jpa.domain.sample.CustomAbstractPersistable</class>
<class>org.springframework.data.jpa.domain.sample.Item</class>
<class>org.springframework.data.jpa.domain.sample.ItemSite</class>
<class>org.springframework.data.jpa.domain.sample.MailMessage</class>
<class>org.springframework.data.jpa.domain.sample.MailSender</class>
<class>org.springframework.data.jpa.domain.sample.MailUser</class>
<class>org.springframework.data.jpa.domain.sample.Product</class>
<class>org.springframework.data.jpa.domain.sample.Role</class>
<class>org.springframework.data.jpa.domain.sample.Site</class>
<class>org.springframework.data.jpa.domain.sample.SpecialUser</class>
<class>org.springframework.data.jpa.domain.sample.User</class>
<class>org.springframework.data.jpa.domain.sample.Dummy</class>
@@ -24,11 +27,14 @@
<class>org.springframework.data.jpa.domain.sample.AuditableRole</class>
<class>org.springframework.data.jpa.domain.sample.Category</class>
<class>org.springframework.data.jpa.domain.sample.CustomAbstractPersistable</class>
<class>org.springframework.data.jpa.domain.sample.Item</class>
<class>org.springframework.data.jpa.domain.sample.ItemSite</class>
<class>org.springframework.data.jpa.domain.sample.MailMessage</class>
<class>org.springframework.data.jpa.domain.sample.MailSender</class>
<class>org.springframework.data.jpa.domain.sample.MailUser</class>
<class>org.springframework.data.jpa.domain.sample.Product</class>
<class>org.springframework.data.jpa.domain.sample.Role</class>
<class>org.springframework.data.jpa.domain.sample.Site</class>
<class>org.springframework.data.jpa.domain.sample.SpecialUser</class>
<class>org.springframework.data.jpa.domain.sample.User</class>
<class>org.springframework.data.jpa.domain.sample.Dummy</class>