Skip to content

Commit

Permalink
fourth solution for result set mappings
Browse files Browse the repository at this point in the history
  • Loading branch information
gavinking committed Dec 20, 2024
1 parent da79526 commit 34806f8
Show file tree
Hide file tree
Showing 5 changed files with 95 additions and 38 deletions.
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package jakarta.persistence.sql;

public record ColumnMapping<T>(String name, Class<T> type)
implements MappingElement<T> {
implements MappingElement<T>, ResultSetMapping<T> {

public static ColumnMapping<Object> of(String name) {
return new ColumnMapping<>(name, Object.class);
Expand Down
14 changes: 14 additions & 0 deletions api/src/main/java/jakarta/persistence/sql/CompoundMapping.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package jakarta.persistence.sql;

public record CompoundMapping(MappingElement<?>[] elements)
implements ResultSetMapping<Object[]> {
public static CompoundMapping of(MappingElement<?>... elements) {
return new CompoundMapping(elements);
}

@Override
public Class<Object[]> type() {
return Object[].class;
}
}

Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
package jakarta.persistence.sql;

public record ConstructorMapping<T>(Class<T> targetClass, ColumnMapping<?>[] columns)
implements MappingElement<T> {
implements MappingElement<T>, ResultSetMapping<T> {

public static <T> ConstructorMapping<T> of(Class<T> targetClass, ColumnMapping<?>... columns) {
return new ConstructorMapping<>(targetClass, columns);
}

@Override
public Class<T> type() {
return targetClass;
}
}
7 changes: 6 additions & 1 deletion api/src/main/java/jakarta/persistence/sql/EntityMapping.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import jakarta.persistence.LockModeType;

public record EntityMapping<T>(Class<T> entityClass, LockModeType lockMode, String discriminatorColumn, MemberMapping<?>[] fields)
implements MappingElement<T> {
implements MappingElement<T>, ResultSetMapping<T> {

@SafeVarargs
public static <T> EntityMapping<T> of(Class<T> entityClass, MemberMapping<T>... fields) {
Expand All @@ -19,4 +19,9 @@ public static <T> EntityMapping<T> of(Class<T> entityClass, String discriminator
public static <T> EntityMapping<T> of(Class<T> entityClass, LockModeType lockMode, String discriminatorColumn, MemberMapping<T>... fields) {
return new EntityMapping<>(entityClass, lockMode, discriminatorColumn, fields);
}

@Override
public Class<T> type() {
return entityClass;
}
}
103 changes: 68 additions & 35 deletions api/src/main/java/jakarta/persistence/sql/ResultSetMapping.java
Original file line number Diff line number Diff line change
@@ -1,37 +1,40 @@
package jakarta.persistence.sql;

import jakarta.persistence.LockModeType;
import jakarta.persistence.metamodel.SingularAttribute;

/**
* Specifies a mapping of the columns of a result set of a SQL query or stored procedure
* to {@linkplain EntityMapping entities}, {@linkplain ColumnMapping scalar values}, and
* {@linkplain ConstructorMapping Java class constructors}.
*
* <p>This class may be instantiated programmatically, for example:
* <p>A {@link ResultSetMapping} may be instantiated programmatically, for example:
* {@snippet :
* import static jakarta.persistence.sql.ResultSetMapping.*;
*
* ...
*
* var entityMapping =
* ResultSetMapping.of(
* EntityMapping.of(Author.class,
* FieldMapping.of(Author_.ssn, "author_ssn"),
* EmbeddableMapping.of(Author_.name,
* FieldMapping.of(Name_.first, "author_first_name"),
* FieldMapping.of(Name_.last, "author_last_name"))));
* entity(Author.class,
* field(Author_.ssn, "auth_ssn"),
* embedded(Author_.name,
* field(Name_.first, "auth_first_name"),
* field(Name_.last, "auth_last_name")));
*
* var constructorMapping =
* ResultSetMapping.of(
* ConstructorMapping.of(Summary.class,
* ColumnMapping.of("book_isbn"),
* ColumnMapping.of("book_title"),
* ColumnMapping.of("book_author")));
* constructor(Summary.class,
* column("isbn"),
* column("title"),
* column("author"));
*
* var mixedMapping =
* ResultSetMapping.of(
* EntityMapping.of(Author.class),
* EntityMapping.of(Book.class,
* FieldMapping.of(Book_.isbn, "book_isbn")),
* ColumnMapping.of("sales", BigDecimal.class),
* ConstructorMapping.of(Summary.class,
* ColumnMapping.of("book_isbn"),
* ColumnMapping.of("book_title")));
* }
* var compoundMapping =
* compound(
* entity(Author.class),
* entity(Book.class, field(Book_.isbn, "isbn")),
* column("sales", BigDecimal.class),
* constructor(Summary.class, column("isbn"), column("title"))
* );
*}
*
* <p>Alternatively, an instance representing a
* {@linkplain jakarta.persistence.SqlResultSetMapping result set mapping defined using annotations}
Expand All @@ -43,25 +46,55 @@
*
* @since 4.0
*/
public record ResultSetMapping<T>(Class<T> resultType, MappingElement<?>[] elements) {
public interface ResultSetMapping<T> {
Class<T> type();

public static ResultSetMapping<Object[]> of(MappingElement<?>... mappings) {
return new ResultSetMapping<>(Object[].class, mappings);
static <T> ColumnMapping<T> column(String name, Class<T> type) {
return ColumnMapping.of(name, type);
}

public static <T> ResultSetMapping<T> of(EntityMapping<T> entityMapping) {
return new ResultSetMapping<>(entityMapping.entityClass(),
new EntityMapping[]{entityMapping});
static ColumnMapping<Object> column(String name) {
return ColumnMapping.of(name);
}

public static <T> ResultSetMapping<T> of(ConstructorMapping<T> constructorMapping) {
return new ResultSetMapping<>(constructorMapping.targetClass(),
new ConstructorMapping[]{constructorMapping});
static <T> ConstructorMapping<T> constructor(Class<T> targetClass, ColumnMapping<?>... columns) {
return ConstructorMapping.of(targetClass, columns);
}

public static <T> ResultSetMapping<T> of(ColumnMapping<T> columnMapping) {
return new ResultSetMapping<>(columnMapping.type(),
new ColumnMapping[]{columnMapping});
static CompoundMapping compound(MappingElement<?>... elements) {
return CompoundMapping.of(elements);
}

@SafeVarargs
static <T> EntityMapping<T> entity(Class<T> entityClass, MemberMapping<T>... fields) {
return EntityMapping.of(entityClass, LockModeType.NONE, "", fields);
}

@SafeVarargs
static <T> EntityMapping<T> entity(Class<T> entityClass, String discriminatorColumn, MemberMapping<T>... fields) {
return EntityMapping.of(entityClass, LockModeType.NONE, discriminatorColumn, fields);
}

@SafeVarargs
static <T> EntityMapping<T> entity(Class<T> entityClass, LockModeType lockMode, String discriminatorColumn, MemberMapping<T>... fields) {
return EntityMapping.of(entityClass, lockMode, discriminatorColumn, fields);
}

@SafeVarargs
static <C,T> EmbeddableMapping<C,T> embedded(Class<C> container, Class<T> embeddableClass, String name, MemberMapping<T>... fields) {
return EmbeddableMapping.of(container, embeddableClass, name, fields);
}

@SafeVarargs
static <C,T> EmbeddableMapping<C,T> embedded(SingularAttribute<C,T> embedded, MemberMapping<T>... fields) {
return EmbeddableMapping.of(embedded.getDeclaringType().getJavaType(), embedded.getJavaType(), embedded.getName(), fields);
}
}

static <C,T> FieldMapping<C,T> field(Class<C> container, Class<T> type, String name, String column) {
return FieldMapping.of(container, type, name, column);
}

static <C,T> FieldMapping<C,T> field(SingularAttribute<C,T> attribute, String column) {
return FieldMapping.of(attribute.getDeclaringType().getJavaType(), attribute.getJavaType(), attribute.getName(), column);
}
}

0 comments on commit 34806f8

Please sign in to comment.