Something like:
public interface ImplicitNamingStrategy { public Identifier determinePrimaryTableName(ImplicitEntityNameSource source); public Identifier determineJoinTableName(ImplicitJoinTableNameSource source); public Identifier determineCollectionTableName(ImplicitCollectionTableNameSource source); public Identifier determineDiscriminatorColumnName(ImplicitDiscriminatorColumnNameSource source); public Identifier determineTenantIdColumnName(ImplicitTenantIdColumnNameSource source); public Identifier determineAttributeColumnName(ImplicitAttributeColumnNameSource source); public Identifier determineCollectionJoinColumnName(ImplicitCollectionJoinColumnNameSource source); ... } The sources are simply parameter objects providing access to information needed to determine the implicit name. For example: /** * Defines the source for entity naming. Between legacy Hibernate requirements and * JPA requirements this is, unfortunately, multi-sourced. This contract allows * access to all source values. * * @author Steve Ebersole */ public interface ImplicitEntityNamingSource { /** * The FQN of the entity class. Note, this may be {@code null} in the case * of (non-JPA-compliant) dynamic entities). * * @return The entity class FQN, or {@code null} if a dynamic entity. */ public String getEntityClassName(); /** * Get the explicitly specified Hibernate entity name. The Hibernate name is * very much different from the JPA concept of entity name. * * @return The explicitly specified entity name */ public String getExplicitEntityName(); /** * The Hibernate entity name. This might be either:<ul> * <li>The explicitly specified entity name, if one</li> * <li>The unqualified entity class name if no entity name was explicitly specified</li> * </ul> * * @return The Hibernate entity name */ public String getEntityName(); /** * The JPA-specific entity name. See {@link javax.persistence.Entity#name()} for details. * * @return The JPA entity name, if one was specified. May return {@code null} if one * was not explicitly specified. */ public String getJpaEntityName(); } etc... And then: public interface PhysicalNamingStrategy { public Identifier toPhysicalCatalogName(Identifier name); public Identifier toPhysicalSchemaName(Identifier name); public Identifier toPhysicalTableName(Identifier name); public Identifier toPhysicalColumnName(Identifier name); } I think ultimately it makes sense to pass some additional information into PhysicalNamingStrategy to give access to Dialect, etc. On Wed, Jan 14, 2015 at 4:38 AM, Hardy Ferentschik <ha...@hibernate.org> wrote: > Hi, > > +1 for ImplicitNamingStrategy and PhysicalNamingStrategy > What would be the contract of these strategies? > > I don't think LogicalNamingStrategy is necessary. I think this might > just get too complicated for a user. Also, iiuc the logical name is for > internal lookups. > > +1 for actual identifier classes. I think the code would become easier to > understand > and hopefully safer with these typed classes. I liked this approach when > working > on the metamodel branch. I would, however, not make it an interface. I > also see > this as a pre-mature optimisation > > > Since JPA does not say what is legal/illegal for the @Column.table > > attribute, it is feasible for us to allow @Column.table to contain the > > catalog/schema information in these cases as a selector.. > > What exactly do you mean with 'selector'? > > --Hardy > > > > On Tue, Jan 13, 2015 at 12:43:37PM -0600, Steve Ebersole wrote: > > As I am working on 5.0, one of the things I am trying to accomplish is to > > make the handling of table/column names more consistent and better > > defined. The first step in that is to properly define the terms used > often > > throughout the codebase. > > > > The first level of naming is the "given" name of a table/column. The > given > > name might be: > > * explicit - explicitly specified by the user, as in @Table( > > name="explicit_name" ) > > * implicit - not explicitly specified by the user and thus implicitly > > determined (by JPA rules, "naming strategy", etc). > > > > Next, we have a logical name which is a normalized form of the "given" > > name. This is the form used to reference tables/columns internally. > E.g., > > its how we resolve @Column(..., table="xyz"). More on this form later. > > > > Finally we have the physical name of the thing, which is the actual name > of > > the table/column in the database. Again, this is generally a > normalization > > of the given name based on Dialect, "naming strategy", etc. > > > > Today, we have a very messy concept called a NamingStrategy. I say it is > > messy because it tries to combine unrelated concerns. So I still plan to > > split this as I have outlined elsewhere into: > > 1) ImplicitNamingStrategy > > 2) PhysicalNamingStrategy > > > > Which brings up my first question to y'all. Do we need a contract for > > LogicalNamingStrategy? As I have said, the logical names are the things > > used to resolve references. Allowing people to plug in custom strategies > > for how that normalization works could be very dangerous. But even more > > than that, is it really interesting to be able to hook into that process? > > > > Historically, these names are all represented by String. So I also > propose > > to shift this to use that Identifier class we developed for the metamodel > > redesign. For those that may be unfamiliar, it essentially combines the > > String name with a "quoted" boolean: > > > > public class Identifier { > > private final String text; > > private final boolean isQuoted; > > ... > > } > > > > Table names, then, are an aggregation of 3 Identifiers: one for catalog, > > one for schema, one for table name. Same for named constraints > > (ultimately, which is part of a improvement for 6.0 to allow indexes, > > constraints, etc to be created in a separate schema from tables). > > > > Since a major goal for 5.0 is to continue to use the > org.hibernate.mapping > > package as the representation of the mapping information, we obviously > want > > to minimize changes there to only what is completely essential. To that > > end, if we are going to use Identifier over String stuff in the > > org.hibernate.mapping package will need to deal with both; internally > they > > will hold the Identifier and use that to implement the String-based > > name-related methods they expose. > > > > Lastly I wanted to discuss the details of the logical names. For tables, > > we currently qualify the table name with the catalog/schema info. There > is > > a mismatch in this regard when it comes to remaining a pure JPA > > implementation. Consider @Column( ..., table="some_table"). Ultimately > we > > need to be able to qualify that with catalog/schema in order to be able > to > > construct a matching logical name (to be able to pair that with the > > referenced org.hibernate.mapping.Table later). This is trivial when > table > > names are unique across all the catalogs/schemas (when there is only one > > "some_table" in all the mapped catalogs/schemas). But is poses a problem > > when the same table name is used from different schemas (e.g., when > > "some_table" is mapped from both "schema1" and "schema2"). So we have a > > choice. Since JPA does not say what is legal/illegal for the > @Column.table > > attribute, it is feasible for us to allow @Column.table to contain the > > catalog/schema information in these cases as a selector. The only other > > option I can see is to define a limitation that says that a table name > must > > be unique for a given entity across all catalogs/schemas. I don't think > > that is generally a restrictive limitation. What are y'alls thoughts? > > Perhaps this is one argument for allowing pluggable > LogicalNamingStrategy? > > _______________________________________________ > > hibernate-dev mailing list > > hibernate-dev@lists.jboss.org > > https://lists.jboss.org/mailman/listinfo/hibernate-dev > _______________________________________________ hibernate-dev mailing list hibernate-dev@lists.jboss.org https://lists.jboss.org/mailman/listinfo/hibernate-dev