Skip to content

Fix #{#entityName} to return table name for native queries #3982

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
package org.springframework.data.jpa.repository.query;

import jakarta.persistence.Entity;
import jakarta.persistence.Table;

import org.springframework.core.annotation.AnnotatedElementUtils;
import org.springframework.util.Assert;
Expand Down Expand Up @@ -53,4 +54,11 @@ public String getEntityName() {
Entity entity = AnnotatedElementUtils.findMergedAnnotation(domainType, Entity.class);
return null != entity && StringUtils.hasText(entity.name()) ? entity.name() : domainType.getSimpleName();
}

@Override
public String getTableName() {

Table table = AnnotatedElementUtils.findMergedAnnotation(domainType, Table.class);
return null != table && StringUtils.hasText(table.name()) ? table.name() : getEntityName();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,14 @@ public interface JpaEntityMetadata<T> extends EntityMetadata<T> {
* @return
*/
String getEntityName();

/**
* Returns the table name from the @Table annotation or defaults to the entity name.
*
* @return the table name
* @since 4.0
*/
default String getTableName() {
return getEntityName();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ public static EntityQuery create(DeclaredQuery declaredQuery, JpaEntityMetadata<

ValueExpressionParser expressionParser = queryContext.getValueExpressionDelegate().getValueExpressionParser();
String resolvedExpressionQuery = renderQueryIfExpressionOrReturnQuery(declaredQuery.getQueryString(),
entityMetadata, expressionParser);
entityMetadata, expressionParser, declaredQuery.isNative());

return EntityQuery.create(declaredQuery.rewrite(resolvedExpressionQuery), queryContext.getSelector());
}
Expand All @@ -98,6 +98,17 @@ public static EntityQuery create(DeclaredQuery declaredQuery, JpaEntityMetadata<
*/
static String renderQueryIfExpressionOrReturnQuery(String query, JpaEntityMetadata<?> metadata,
ValueExpressionParser parser) {
return renderQueryIfExpressionOrReturnQuery(query, metadata, parser, false);
}

/**
* @param query, the query expression potentially containing a SpEL expression. Must not be {@literal null}.
* @param metadata the {@link JpaEntityMetadata} for the given entity. Must not be {@literal null}.
* @param parser Must not be {@literal null}.
* @param isNative whether the query is a native SQL query.
*/
static String renderQueryIfExpressionOrReturnQuery(String query, JpaEntityMetadata<?> metadata,
ValueExpressionParser parser, boolean isNative) {

Assert.notNull(query, "query must not be null");
Assert.notNull(metadata, "metadata must not be null");
Expand All @@ -108,7 +119,10 @@ static String renderQueryIfExpressionOrReturnQuery(String query, JpaEntityMetada
}

SimpleEvaluationContext evalContext = SimpleEvaluationContext.forReadOnlyDataBinding().build();
evalContext.setVariable(ENTITY_NAME, metadata.getEntityName());

String entityNameValue = isNative ? metadata.getTableName() : metadata.getEntityName();

evalContext.setVariable(ENTITY_NAME, entityNameValue);

query = potentiallyQuoteExpressionsParameter(query);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -783,6 +783,14 @@ void executesNativeQueryCorrectly() {
assertThat(repository.findNativeByLastname("Matthews")).containsOnly(thirdUser);
}

@Test // GH-3979
void executesNativeQueryWithSelectStarCorrectly() {

flushTestUsers();

assertThat(repository.findNativeWithSelectStar("Matthews")).containsOnly(thirdUser);
}

@Test // DATAJPA-132
void executesFinderWithTrueKeywordCorrectly() {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -676,6 +676,10 @@ List<String> findAllAndSortByFunctionResultNamedParameter(@Param("namedParameter
@Query(value = "VALUES (1)", nativeQuery = true)
List<Integer> valuesStatementNative();

// GH-3979
@Query(value = "select * from #{#entityName} where lastname = ?1", nativeQuery = true)
List<User> findNativeWithSelectStar(String lastname);

// GH-2578
@Query(value = "with sample_data as ( Select * from SD_User u where u.age > 30 ) \n select * from sample_data",
nativeQuery = true)
Expand Down