Skip to content
Closed
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
8 changes: 6 additions & 2 deletions api/src/main/java/jakarta/persistence/EntityHandler.java
Original file line number Diff line number Diff line change
Expand Up @@ -681,7 +681,8 @@ <T> List<T> findMultiple(EntityGraph<T> graph, List<?> ids,
* <ol>
* <li>the select list of the query contains only a single
* item, which must be assignable to the result class,
* <li>the result class is {@code Object[].class}, or
* <li>the result class is {@code Object[].class} or
* {@link Tuple Tuple.class}, or
* <li>the result class is a non-abstract class or record
* type with a constructor with the same number of
* parameters as the query has items in its select list,
Expand All @@ -692,7 +693,10 @@ <T> List<T> findMultiple(EntityGraph<T> graph, List<?> ids,
* directly to the caller. In the second case, each query
* result is packaged in an array with the array elements
* corresponding by position with the items of the query
* select list. In the third case, each query result is
* select list or in an instance of {@link Tuple} with the
* indices and aliases of the tuple elements determined by
* the positions and aliases of the corresponding items in
* the select list. In the third case, each query result is
* automatically packaged in a new instance of the result
* class by calling the matching constructor.
* @param qlString A Jakarta Persistence query string
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -531,11 +531,11 @@ public interface EntityManagerFactory extends AutoCloseable {
* A map keyed by {@linkplain SqlResultSetMapping#name name}, containing
* a typed {@link ResultSetMapping} for every result set mapping defined
* {@linkplain SqlResultSetMapping in annotations} whose inferred result
* type is assignable to the given Java type.
* type is exactly the given Java type.
* @param resultType any Java type, including {@code Object.class}
* meaning all result set mappings
* @return a map keyed by query name
* @param <R> the specified upper bound on the query result types
* @param <R> the specified query result type
*
* @since 4.0
*/
Expand Down
17 changes: 13 additions & 4 deletions api/src/main/java/jakarta/persistence/sql/ColumnMapping.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
*
* @since 4.0
*/
public record ColumnMapping<T>(String columnName, Class<T> type)
public record ColumnMapping<T>(String columnName, Class<T> type, String alias)
implements MappingElement<T>, ResultSetMapping<T> {

public ColumnMapping {
Expand All @@ -50,15 +50,24 @@ public Class<T> getJavaType() {
*/
@Override
public String getAlias() {
return columnName;
return alias;
}

/**
* Specify an alias for this column in the result set.
* @param alias The alias
*/
@Override
public ColumnMapping<T> withAlias(String alias) {
return new ColumnMapping<>(columnName, type, alias);
}

/**
* Construct a new instance.
* @param columnName The name of the mapped column of the result set
*/
public static ColumnMapping<Object> of(String columnName) {
return new ColumnMapping<>(columnName, Object.class);
return new ColumnMapping<>(columnName, Object.class, columnName);
}

/**
Expand All @@ -68,6 +77,6 @@ public static ColumnMapping<Object> of(String columnName) {
* @param <T> The type of the resulting scalar value
*/
public static <T> ColumnMapping<T> of(String columnName, Class<T> type) {
return new ColumnMapping<>(columnName, type);
return new ColumnMapping<>(columnName, type, columnName);
}
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assume your expectation here is to just directly construct the ColumnMapping to apply an alias as opposed to having a factory method?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah I would use:

    column("name").withAlias("alias")

Or:

column("name", int.class).withAlias("alias")

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you prefer, we could rename withAlias to as.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like withAlias better here.

23 changes: 18 additions & 5 deletions api/src/main/java/jakarta/persistence/sql/ConstructorMapping.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,10 @@
* @since 4.0
*/

public record ConstructorMapping<T>(Class<T> targetClass, MappingElement<?>[] arguments)
public record ConstructorMapping<T>(Class<T> targetClass, MappingElement<?>[] arguments, String alias)
implements MappingElement<T>, ResultSetMapping<T> {

public ConstructorMapping(Class<T> targetClass, MappingElement<?>[] arguments) {
public ConstructorMapping(Class<T> targetClass, MappingElement<?>[] arguments, String alias) {
requireNonNull(targetClass, "targetClass is required");
requireNonNull(arguments, "arguments are required");
if (arguments.length == 0) {
Expand All @@ -44,6 +44,7 @@ public ConstructorMapping(Class<T> targetClass, MappingElement<?>[] arguments) {
}
this.targetClass = targetClass;
this.arguments = arguments.clone();
this.alias = alias;
}

@Override
Expand All @@ -60,11 +61,23 @@ public Class<T> getJavaType() {
}

/**
* Always returns {@code null}.
* Return the alias specified via {@link #withAlias},
* which may be used to retrieve a constructed value using
* {@link jakarta.persistence.Tuple#get(String, Class)}
* @return the explicitly specified alias or {@code null}
*/
@Override
public String getAlias() {
return null;
return alias;
}

/**
* Specify an alias for this constructor result in the result set.
* @param alias The alias
*/
@Override
public ConstructorMapping<T> withAlias(String alias) {
return new ConstructorMapping<>(targetClass, arguments, alias);
}

/**
Expand All @@ -74,7 +87,7 @@ public String getAlias() {
* @param <T> The type of the Java class
*/
public static <T> ConstructorMapping<T> of(Class<T> targetClass, MappingElement<?>... arguments) {
return new ConstructorMapping<>(targetClass, arguments);
return new ConstructorMapping<>(targetClass, arguments, null);
}

/**
Expand Down
45 changes: 25 additions & 20 deletions api/src/main/java/jakarta/persistence/sql/EntityMapping.java
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,10 @@
* @since 4.0
*/
public record EntityMapping<T>
(Class<T> entityClass, LockModeType lockMode, String discriminatorColumn, MemberMapping<?>[] fields)
(Class<T> entityClass, LockModeType lockMode, String discriminatorColumn, MemberMapping<?>[] fields, String alias)
implements MappingElement<T>, ResultSetMapping<T> {

public EntityMapping(Class<T> entityClass, LockModeType lockMode, String discriminatorColumn, MemberMapping<?>[] fields) {
public EntityMapping(Class<T> entityClass, LockModeType lockMode, String discriminatorColumn, MemberMapping<?>[] fields, String alias) {
requireNonNull(entityClass, "entityClass is required");
requireNonNull(lockMode, "lockMode is required");
if (discriminatorColumn != null && discriminatorColumn.isBlank()) {
Expand All @@ -56,6 +56,7 @@ public EntityMapping(Class<T> entityClass, LockModeType lockMode, String discrim
this.lockMode = lockMode;
this.discriminatorColumn = discriminatorColumn;
this.fields = fields.clone();
this.alias = alias;
}

@Override
Expand All @@ -72,43 +73,47 @@ public Class<T> getJavaType() {
}

/**
* Always returns {@code null}.
* Return the alias specified via {@link #withAlias},
* which may be used to retrieve an entity instance using
* {@link jakarta.persistence.Tuple#get(String, Class)}
* @return the explicitly specified alias or {@code null}
*/
@Override
public String getAlias() {
return null;
return alias;
}

/**
* Construct a new instance.
* @param entityClass The entity class
* @param fields Mappings for fields or properties of the entity
* @param <T> The entity type
* Specify an alias for this entity in the result set.
* @param alias The alias
*/
@SafeVarargs
public static <T> EntityMapping<T> of(Class<T> entityClass, MemberMapping<T>... fields) {
return new EntityMapping<>(entityClass, LockModeType.NONE, null, fields);
@Override
public EntityMapping<T> withAlias(String alias) {
return new EntityMapping<>(entityClass, lockMode, discriminatorColumn, fields, alias);
}

/**
* Specify the lock mode obtained on this entity.
* @param lockMode The lock mode
*/
public EntityMapping<T> withLockMode(LockModeType lockMode) {
return new EntityMapping<>(entityClass, lockMode, discriminatorColumn, fields, alias);
}

/**
* Construct a new instance.
* @param entityClass The entity class
* @param discriminatorColumn The name of the column holding the
* {@linkplain jakarta.persistence.DiscriminatorColumn
* discriminator}; a {@code null} value indicates that
* there is no discriminator column.
* @param fields Mappings for fields or properties of the entity
* @param <T> The entity type
*/
@SafeVarargs
public static <T> EntityMapping<T> of(Class<T> entityClass, String discriminatorColumn, MemberMapping<T>... fields) {
return new EntityMapping<>(entityClass, LockModeType.NONE, discriminatorColumn, fields);
public static <T> EntityMapping<T> of(Class<T> entityClass, MemberMapping<T>... fields) {
return new EntityMapping<>(entityClass, LockModeType.NONE, null, fields, null);
}

/**
* Construct a new instance.
* @param entityClass The entity class
* @param lockMode The lock mode acquired by the SQL query
* @param discriminatorColumn The name of the column holding the
* {@linkplain jakarta.persistence.DiscriminatorColumn
* discriminator}; a {@code null} value indicates that
Expand All @@ -117,8 +122,8 @@ public static <T> EntityMapping<T> of(Class<T> entityClass, String discriminator
* @param <T> The entity type
*/
@SafeVarargs
public static <T> EntityMapping<T> of(Class<T> entityClass, LockModeType lockMode, String discriminatorColumn, MemberMapping<T>... fields) {
return new EntityMapping<>(entityClass, lockMode, discriminatorColumn, fields);
public static <T> EntityMapping<T> of(Class<T> entityClass, String discriminatorColumn, MemberMapping<T>... fields) {
return new EntityMapping<>(entityClass, LockModeType.NONE, discriminatorColumn, fields, null);
}

/**
Expand Down
5 changes: 5 additions & 0 deletions api/src/main/java/jakarta/persistence/sql/MappingElement.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,9 @@
*/
public sealed interface MappingElement<T> extends TupleElement<T>
permits EntityMapping, ColumnMapping, ConstructorMapping {
/**
* Specify an alias for this element of the result set.
* @param alias The alias
*/
MappingElement<T> withAlias(String alias);
Comment thread
gavinking marked this conversation as resolved.
}
16 changes: 0 additions & 16 deletions api/src/main/java/jakarta/persistence/sql/ResultSetMapping.java
Original file line number Diff line number Diff line change
Expand Up @@ -157,22 +157,6 @@ static <T> EntityMapping<T> entity(Class<T> entityClass, String discriminatorCol
return EntityMapping.of(entityClass, discriminatorColumn, fields);
}

/**
* Construct a mapping for an entity class.
*
* @param entityClass The Java class of the entity
* @param lockMode The lock mode acquired by SQL query
* @param discriminatorColumn The name of the column holding the discriminator;
* an empty string indicates that there is no discriminator column
* @param fields Mappings for fields or properties of the entity
*
* @see jakarta.persistence.EntityResult
*/
@SafeVarargs
static <T> EntityMapping<T> entity(Class<T> entityClass, LockModeType lockMode, String discriminatorColumn, MemberMapping<T>... fields) {
return EntityMapping.of(entityClass, lockMode, discriminatorColumn, fields);
}

/**
* Construct a mapping for an embedded object.
*
Expand Down
8 changes: 8 additions & 0 deletions api/src/main/java/jakarta/persistence/sql/TupleMapping.java
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,14 @@
* });
* }
*
* <p>Each result {@link Tuple} contains an entry for each
* {@linkplain #elements element} of the {@code TupleMapping}.
* The index and alias of a tuple entry are determined by the
* position of the element in {@code TupleMapping} and the
* {@linkplain MappingElement#getAlias alias} of the element,
* respectively.
*
*
* @param elements Mappings for the elements of the tuple
*
* @see CompoundMapping
Expand Down
14 changes: 7 additions & 7 deletions spec/src/main/asciidoc/appG-resultset-mappings.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

The following APIs are defined in the package `jakarta.persistence.sql`.

=== `ResultSetMapping`
=== `ResultSetMapping` [[_result-set-mapping_]]
[source,java]
----
include::../../../../api/src/main/java/jakarta/persistence/sql/ResultSetMapping.java[lines=18..-1]
Expand All @@ -21,25 +21,25 @@ include::../../../../api/src/main/java/jakarta/persistence/sql/MappingElement.ja
include::../../../../api/src/main/java/jakarta/persistence/sql/MemberMapping.java[lines=18..-1]
----

=== `ColumnMapping`
=== `ColumnMapping` [[_column-mapping_]]
[source,java]
----
include::../../../../api/src/main/java/jakarta/persistence/sql/ColumnMapping.java[lines=18..-1]
----

=== `FieldMapping`
=== `FieldMapping` [[_field-mapping_]]
[source,java]
----
include::../../../../api/src/main/java/jakarta/persistence/sql/FieldMapping.java[lines=18..-1]
----

=== `EntityMapping`
=== `EntityMapping` [[_entity-mapping_]]
[source,java]
----
include::../../../../api/src/main/java/jakarta/persistence/sql/EntityMapping.java[lines=18..-1]
----

=== `EmbeddedMapping`
=== `EmbeddedMapping` [[_embedded-mapping_]]
[source,java]
----
include::../../../../api/src/main/java/jakarta/persistence/sql/EmbeddedMapping.java[lines=18..-1]
Expand All @@ -51,13 +51,13 @@ include::../../../../api/src/main/java/jakarta/persistence/sql/EmbeddedMapping.j
include::../../../../api/src/main/java/jakarta/persistence/sql/CompoundMapping.java[lines=18..-1]
----

=== `ConstructorMapping`
=== `ConstructorMapping` [[_constructor-mapping_]]
[source,java]
----
include::../../../../api/src/main/java/jakarta/persistence/sql/ConstructorMapping.java[lines=18..-1]
----

=== `TupleMapping`
=== `TupleMapping` [[_tuple-mapping_]]
[source,java]
----
include::../../../../api/src/main/java/jakarta/persistence/sql/TupleMapping.java[lines=18..-1]
Expand Down
Loading