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 <hardy(a)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(a)lists.jboss.org
>
https://lists.jboss.org/mailman/listinfo/hibernate-dev