jakartaee / persistence

https://jakartaee.github.io/persistence/
Other
206 stars 59 forks source link

Easier column name overriding in embedded mappings #322

Closed sebersole closed 3 years ago

sebersole commented 3 years ago
@Embeddable
class Name {
    String getFirst() { ... }
    String getLast() { ... }
}

Implicitly, the column names for this embeddable will be first and last.

@Entity
class Person {
    ...

    @Embedded
    Name getName();
}

With no overrides, the column names used here will be Person.first and Person.last.

It is quite common to adjust the name of the columns to indicate the "usage":

@Entity
class Person {
    ...
    @Embedded
    @AttributeOverride(name="first",column=@Column(name="first_name"))
    @AttributeOverride(name="last",column=@Column(name="last_name"))
    Name getName();
}

That's getting a littler verbose, even for such a small embeddable and just a single usage.

Of course, as long as the user controls the Name class they could simply rename the columns in the Name class. But that is not always the case.

Strictly by the spec, users would have to use the AttributeOverride when mapping multiple embeddeds.

@Entity
class NamePair {
    ...
    @Embedded
    Name getLeft() { ... }

    @Embedded
    Name getRight() { ... }
}

This mapping would not work because it maps both of the columns twice. To be portable, a user would be forced to define @AttributeOverrides for at least one of these attributes.

class NamePair {
    ...
    @Embedded
    @AttributeOverride(name="first",column=@Column(name="left_first"))
    @AttributeOverride(name="last",column=@Column(name="left_last"))
    Name getLeft() { ... }

    @Embedded
    Name getRight() { ... }
}

And really most people are going to want to override all of them as columns named left_first, left_last, first, last seems a bit odd..

class NamePair {
    ...
    @Embedded
    @AttributeOverride(name="first",column=@Column(name="left_first"))
    @AttributeOverride(name="last",column=@Column(name="left_last"))
    Name getLeft() { ... }

    @Embedded
    @AttributeOverride(name="first",column=@Column(name="right_first"))
    @AttributeOverride(name="last",column=@Column(name="right_last"))
    Name getRight() { ... }
}

That's pretty verbose for such a common pattern.

I propose adding the following methods to @Embedded:

@interface Embedded {
    ...

    /**
     * Prepend the value to the name of any column contained in this embedded.
     * 
     * code block with example...
     */
    String columnPrefix() default "";

    /**
     * Append the value to the name of any column contained in this embedded.
     * 
     * code block with example...
     */
    String columnPostfix() default "";
}

Or maybe even

@Embedded {
    ...

    /**
     * Define a template to apply to the names of columns contained in the embedded.
     * 
     * code block with example...
     * 
     * @see String#format
     */
    String columnNameFormat() "";
}

The last allowing, e.g.


class NamePair {
    ...
    @Embedded( columnNameFormat = "left_%s" );
    Name getLeft() { ... }

    @Embedded( columnNameFormat = "right_%s" );
    Name getRight() { ... }
}
rbygrave commented 3 years ago

To me this looks similar to https://github.com/eclipse-ee4j/jpa-api/issues/23 ? Is is possible to merge the 2 issues into one?

sebersole commented 3 years ago

Ah true. Sorry, I only went back a few pages in the issues :)