DATAJPA-509 - JpaMetamodelEntityInformation now considers entity name from JPA meta-model.
JpaMetamodelEntityInformation prefers the entity name from the JPA meta-model over the one derived from the simple class name. Documented limitation of an entity name customized through XML mapping metadata will not be considered in the SpEL support for manually defined query methods. Original pull request: #76.
This commit is contained in:
committed by
Oliver Gierke
parent
4dd570f670
commit
ff0170967d
@@ -321,7 +321,7 @@ class ApplicationConfig {
|
||||
<entry><code>… where x.lastname = ?1 or x.firstname =
|
||||
?2</code></entry>
|
||||
</row>
|
||||
|
||||
|
||||
<row>
|
||||
<entry><code>Is,Equals</code></entry>
|
||||
|
||||
@@ -346,7 +346,7 @@ class ApplicationConfig {
|
||||
|
||||
<entry><code>… where x.age < ?1</code></entry>
|
||||
</row>
|
||||
|
||||
|
||||
<row>
|
||||
<entry><code>LessThanEqual</code></entry>
|
||||
|
||||
@@ -362,7 +362,7 @@ class ApplicationConfig {
|
||||
|
||||
<entry><code>… where x.age > ?1</code></entry>
|
||||
</row>
|
||||
|
||||
|
||||
<row>
|
||||
<entry><code>GreaterThanEqual</code></entry>
|
||||
|
||||
@@ -496,15 +496,15 @@ class ApplicationConfig {
|
||||
|
||||
<entry><code>… where x.active = false</code></entry>
|
||||
</row>
|
||||
|
||||
|
||||
<row>
|
||||
<entry><code>IgnoreCase</code></entry>
|
||||
|
||||
<entry><code>findByFirstnameIgnoreCase</code></entry>
|
||||
|
||||
<entry><code>… where UPPER(x.firstame) = UPPER(?1)</code></entry>
|
||||
<entry><code>… where UPPER(x.firstame) =
|
||||
UPPER(?1)</code></entry>
|
||||
</row>
|
||||
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</table><note>
|
||||
@@ -748,6 +748,13 @@ public class User {
|
||||
the query string of a <code>@Query</code> annotation one can use the
|
||||
<code>#{#entityName}</code> Variable.</para>
|
||||
|
||||
<note>
|
||||
<para>The <code>entityName</code> can be customized via the
|
||||
<code>@Entity</code> annotation. Customizations via
|
||||
<literal>orm.xml</literal> are not supported for the SpEL
|
||||
expressions.</para>
|
||||
</note>
|
||||
|
||||
<example>
|
||||
<title>Using SpEL expressions in Repository query methods -
|
||||
entityName</title>
|
||||
@@ -1067,7 +1074,7 @@ class UserManagementImpl implements UserManagement {
|
||||
none already running). The transaction configuration at the repositories
|
||||
will be neglected then as the outer transaction configuration determines
|
||||
the actual one used. Note that you will have to activate
|
||||
<code><tx:annotation-driven /></code> or use
|
||||
<code><tx:annotation-driven /></code> or use
|
||||
<interfacename>@EnableTransactionManagement</interfacename> explicitly
|
||||
to get annotation based configuration at facades working. The example
|
||||
above assumes you are using component scanning.</para>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2011-2013 the original author or authors.
|
||||
* Copyright 2011-2014 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.
|
||||
@@ -23,6 +23,7 @@ import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.persistence.IdClass;
|
||||
import javax.persistence.metamodel.EntityType;
|
||||
import javax.persistence.metamodel.IdentifiableType;
|
||||
import javax.persistence.metamodel.ManagedType;
|
||||
import javax.persistence.metamodel.Metamodel;
|
||||
@@ -48,6 +49,7 @@ public class JpaMetamodelEntityInformation<T, ID extends Serializable> extends J
|
||||
private final IdMetadata<T> idMetadata;
|
||||
private final SingularAttribute<? super T, ?> versionAttribute;
|
||||
private final Metamodel metamodel;
|
||||
private final String entityName;
|
||||
|
||||
/**
|
||||
* Creates a new {@link JpaMetamodelEntityInformation} for the given domain class and {@link Metamodel}.
|
||||
@@ -63,11 +65,12 @@ public class JpaMetamodelEntityInformation<T, ID extends Serializable> extends J
|
||||
this.metamodel = metamodel;
|
||||
|
||||
ManagedType<T> type = metamodel.managedType(domainClass);
|
||||
|
||||
if (type == null) {
|
||||
throw new IllegalArgumentException("The given domain class can not be found in the given Metamodel!");
|
||||
}
|
||||
|
||||
this.entityName = type instanceof EntityType ? ((EntityType<?>) type).getName() : null;
|
||||
|
||||
if (!(type instanceof IdentifiableType)) {
|
||||
throw new IllegalArgumentException("The given domain class does not contain an id attribute!");
|
||||
}
|
||||
@@ -76,6 +79,15 @@ public class JpaMetamodelEntityInformation<T, ID extends Serializable> extends J
|
||||
this.versionAttribute = findVersionAttribute(type);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.jpa.repository.support.JpaEntityInformationSupport#getEntityName()
|
||||
*/
|
||||
@Override
|
||||
public String getEntityName() {
|
||||
return entityName != null ? entityName : super.getEntityName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the version attribute of the given {@link ManagedType} or {@literal null} if none available.
|
||||
*
|
||||
@@ -126,9 +138,7 @@ public class JpaMetamodelEntityInformation<T, ID extends Serializable> extends J
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.springframework.data.repository.support.EntityInformation#getIdType()
|
||||
* @see org.springframework.data.repository.core.EntityInformation#getIdType()
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public Class<ID> getIdType() {
|
||||
@@ -137,9 +147,7 @@ public class JpaMetamodelEntityInformation<T, ID extends Serializable> extends J
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.springframework.data.jpa.repository.support.JpaEntityMetadata#
|
||||
* getIdAttribute()
|
||||
* @see org.springframework.data.jpa.repository.support.JpaEntityInformation#getIdAttribute()
|
||||
*/
|
||||
public SingularAttribute<? super T, ?> getIdAttribute() {
|
||||
return idMetadata.getSimpleIdAttribute();
|
||||
|
||||
@@ -36,9 +36,7 @@ public class Role {
|
||||
/**
|
||||
* Creates a new instance of {@code Role}.
|
||||
*/
|
||||
public Role() {
|
||||
|
||||
}
|
||||
public Role() {}
|
||||
|
||||
/**
|
||||
* Creates a new preconfigured {@code Role}.
|
||||
@@ -46,7 +44,6 @@ public class Role {
|
||||
* @param name
|
||||
*/
|
||||
public Role(final String name) {
|
||||
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@@ -60,6 +57,13 @@ public class Role {
|
||||
return id;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the name
|
||||
*/
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2011 the original author or authors.
|
||||
* Copyright 2011-2014 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.
|
||||
@@ -32,14 +32,14 @@ import org.springframework.transaction.annotation.Transactional;
|
||||
* Integration tests for {@link RoleRepository}.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @author Thomas Darimont
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration(locations = { "classpath:application-context.xml" })
|
||||
@Transactional
|
||||
public class RoleRepositoryIntegrationTests {
|
||||
|
||||
@Autowired
|
||||
RoleRepository repository;
|
||||
@Autowired RoleRepository repository;
|
||||
|
||||
@Test
|
||||
public void createsRole() throws Exception {
|
||||
@@ -62,4 +62,40 @@ public class RoleRepositoryIntegrationTests {
|
||||
|
||||
assertThat(repository.findOne(result.getId()), is(reference));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAJPA-509
|
||||
*/
|
||||
@Test
|
||||
public void shouldUseExplicitlyConfiguredEntityNameInOrmXmlInCountQueries() {
|
||||
|
||||
Role reference = new Role("ADMIN");
|
||||
repository.save(reference);
|
||||
|
||||
assertThat(repository.count(), is(1L));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAJPA-509
|
||||
*/
|
||||
@Test
|
||||
public void shouldUseExplicitlyConfiguredEntityNameInOrmXmlInExistsQueries() {
|
||||
|
||||
Role reference = new Role("ADMIN");
|
||||
reference = repository.save(reference);
|
||||
|
||||
assertThat(repository.exists(reference.getId()), is(true));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAJPA-509
|
||||
*/
|
||||
@Test
|
||||
public void shouldUseExplicitlyConfiguredEntityNameInDerivedCountQueries() {
|
||||
|
||||
Role reference = new Role("ADMIN");
|
||||
reference = repository.save(reference);
|
||||
|
||||
assertThat(repository.countByName(reference.getName()), is(1L));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2008-2011 the original author or authors.
|
||||
* Copyright 2008-2014 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.
|
||||
@@ -32,22 +32,22 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
* Integration test for XML configuration of {@link QueryLookupStrategy.Key}s.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @author Thomas Darimont
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration(locations = "classpath:config/lookup-strategies-context.xml")
|
||||
public class QueryLookupStrategyTests {
|
||||
|
||||
@Autowired
|
||||
ApplicationContext context;
|
||||
@Autowired ApplicationContext context;
|
||||
|
||||
/**
|
||||
* Assert that {@link QueryLookupStrategy#USE_DECLARED_QUERY} is being set on the factory if configured.
|
||||
* Assert that {@link Key#CREATE_IF_NOT_FOUND} is being set on the factory if configured.
|
||||
*/
|
||||
@Test
|
||||
public void assertUseDeclaredQuery() {
|
||||
public void shouldUseExplicitlyConfiguredQueryLookUpStrategy() {
|
||||
|
||||
JpaRepositoryFactoryBean<?, ?, ?> factory = context.getBean("&roleRepository", JpaRepositoryFactoryBean.class);
|
||||
|
||||
assertEquals(Key.USE_DECLARED_QUERY, getField(factory, "queryLookupStrategyKey"));
|
||||
assertEquals(Key.CREATE_IF_NOT_FOUND, getField(factory, "queryLookupStrategyKey"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@ import org.springframework.data.repository.CrudRepository;
|
||||
* Typing interface for {@code Role}.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @author Thomas Darimont
|
||||
*/
|
||||
public interface RoleRepository extends CrudRepository<Role, Integer> {
|
||||
|
||||
@@ -45,4 +46,9 @@ public interface RoleRepository extends CrudRepository<Role, Integer> {
|
||||
@Lock(LockModeType.READ)
|
||||
@QueryHints(@QueryHint(name = "foo", value = "bar"))
|
||||
Role findOne(Integer id);
|
||||
|
||||
/**
|
||||
* @see DATAJPA-509
|
||||
*/
|
||||
long countByName(String name);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2011-2013 the original author or authors.
|
||||
* Copyright 2011-2014 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.
|
||||
@@ -36,6 +36,7 @@ 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.Role;
|
||||
import org.springframework.data.jpa.domain.sample.SampleWithIdClass;
|
||||
import org.springframework.data.jpa.domain.sample.SampleWithIdClassPK;
|
||||
import org.springframework.data.jpa.domain.sample.SampleWithPrimitiveId;
|
||||
@@ -49,6 +50,7 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
* Integration tests for {@link JpaMetamodelEntityInformation}.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @author Thomas Darimont
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration({ "classpath:infrastructure.xml" })
|
||||
@@ -155,6 +157,18 @@ public class JpaMetamodelEntityInformationIntegrationTests {
|
||||
assertThat(information.isNew(sample), is(false));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAJPA-509
|
||||
*/
|
||||
@Test
|
||||
public void jpaMetamodelEntityInformationShouldRespectExplicitlyConfiguredEntityNameFromOrmXml() {
|
||||
|
||||
JpaEntityInformation<Role, Integer> info = new JpaMetamodelEntityInformation<Role, Integer>(Role.class,
|
||||
em.getMetamodel());
|
||||
|
||||
assertThat(info.getEntityName(), is("ROLE"));
|
||||
}
|
||||
|
||||
protected String getMetadadataPersitenceUnitName() {
|
||||
return "metadata";
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
<query>SELECT u FROM User u WHERE u.lastname = ?1</query>
|
||||
</named-query>
|
||||
|
||||
<entity class="org.springframework.data.jpa.domain.sample.Role" access="FIELD">
|
||||
<entity class="org.springframework.data.jpa.domain.sample.Role" access="FIELD" name="ROLE">
|
||||
<attributes>
|
||||
<id name="id">
|
||||
<generated-value strategy="AUTO" />
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
<import resource="../infrastructure.xml" />
|
||||
|
||||
<jpa:repositories base-package="org.springframework.data.jpa.repository.sample" query-lookup-strategy="use-declared-query">
|
||||
<jpa:repositories base-package="org.springframework.data.jpa.repository.sample" query-lookup-strategy="create-if-not-found">
|
||||
<repository:include-filter type="assignable" expression="org.springframework.data.jpa.repository.sample.RoleRepository" />
|
||||
</jpa:repositories>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user