Hibernate 5 ImplicitNamingStrategy

时间:2015-10-13 20:23:59

标签: hibernate hibernate-5.x

我想使用hibernate 5.x.对于hibernate 5.x,ImplicitNamingStrategyPhysicalNamingStrategy有新的接口。

对于实体name的属性User,我希望在我的数据库中有一个列名user_name。我不想用@Column(name="...")注释每个属性。我尝试编写自定义ImplicitNamingStrategy,但无法获取拥有实体的名称。

public class MyNamingStrategy extends ImplicitNamingStrategyComponentPathImpl
{
    @Override
    public Identifier determineBasicColumnName ( ImplicitBasicColumnNameSource source )
    {
        // How to get the name of the owning entity?
        String owningEntityName = "howdoigetthis"; 
        Identifier basicColumnName = super.determineBasicColumnName(source);
        Identifier identifier = Identifier.toIdentifier(owningEntityName +"_" + basicColumnName.toString());
        return identifier;
    }
}

有没有办法只使用NamingStrategy为每个列添加表(或实体)名称?

3 个答案:

答案 0 :(得分:3)

如果你不介意一些肮脏的反思,这里有一个解决方案:

Declare row FOR SELECT...
INSERT row INTO ... 

答案 1 :(得分:3)

根据Steve Chambers的回答,这是我的最终解决方案。此解决方案甚至考虑了带注释的显式命名并修复了连接列名称。但史蒂夫应该得到他的答案的所有优点

public class JlotImplicitNamingStrategy extends ImplicitNamingStrategyComponentPathImpl
{
    @Override
    public Identifier determineJoinColumnName ( ImplicitJoinColumnNameSource source )
    {
        String name = source.getReferencedColumnName().toString();
        Identifier identifier = toIdentifier(name, source.getBuildingContext());
        return identifier;
    }

    @Override
    public Identifier determineBasicColumnName ( ImplicitBasicColumnNameSource source )
    {
        try
        {
            Field ejb3ColumnField = source.getClass().getDeclaredField("this$0");
            ejb3ColumnField.setAccessible(true);
            Ejb3Column ejb3Column = (Ejb3Column) ejb3ColumnField.get(source);

            // explicit naming oder implicit
            String tableName = ejb3Column.getPropertyHolder().getTable().getName();
            final Identifier basicColumnName = super.determineBasicColumnName(source);
            String columnName = tableName + "_" + basicColumnName.toString();
            return Identifier.toIdentifier(columnName);
        }
        catch (IllegalArgumentException | IllegalAccessException | NoSuchFieldException | SecurityException e)
        {
            throw new RuntimeException(e);
        }
    }
}

答案 2 :(得分:2)

我已经实现了两个接口,它们提供了99.99%的结果作为hibernate 4:

public class ImprovedNamingStrategy implements PhysicalNamingStrategy
{

@Override
public Identifier toPhysicalCatalogName(Identifier identifier, JdbcEnvironment jdbcEnv)
{
    return convert(identifier);
}

@Override
public Identifier toPhysicalColumnName(Identifier identifier, JdbcEnvironment jdbcEnv)
{
    return convert(identifier);
}

@Override
public Identifier toPhysicalSchemaName(Identifier identifier, JdbcEnvironment jdbcEnv)
{
    return convert(identifier);
}

@Override
public Identifier toPhysicalSequenceName(Identifier identifier, JdbcEnvironment jdbcEnv)
{
    return convert(identifier);
}

@Override
public Identifier toPhysicalTableName(Identifier identifier, JdbcEnvironment jdbcEnv)
{
    return convert(identifier);
}

/**
 * Converts table name.
 *
 * @param identifier the identifier.
 * @return the identifier.
 */
private Identifier convert(Identifier identifier)
{
    if (identifier == null || StringUtils.isBlank(identifier.getText()))
    {
        return identifier;
    }

    final StringBuilder buf = new StringBuilder(identifier.getText().replace('.', '_'));
    for (int i = 1; i < buf.length() - 1; i++)
    {
        if (
            Character.isLowerCase(buf.charAt(i - 1)) &&
            Character.isUpperCase(buf.charAt(i)) &&
            Character.isLowerCase(buf.charAt(i + 1))
            )
        {
            buf.insert(i++, '_');
        }
    }
    String newName = Strings.toLowerCase(buf.toString());
    return Identifier.toIdentifier(newName);
}
}

public class ImprovedImplicitNamingStrategy implements ImplicitNamingStrategy
{
/**
 * The INSTANCE.
 */
public static final ImprovedImplicitNamingStrategy INSTANCE = new ImprovedImplicitNamingStrategy();

/**
 * Constructor.
 */
public ImprovedImplicitNamingStrategy()
{
}

/**
 * The determinePrimaryTableName.
 *
 * @param source the source.
 * @return the identifier.
 */
@Override
public Identifier determinePrimaryTableName(ImplicitEntityNameSource source)
{
    if (source == null)
    {
        // should never happen, but to be defensive...
        throw new HibernateException("Entity naming information was not provided.");
    }

    String tableName = transformEntityName(source.getEntityNaming());

    if (tableName == null)
    {
        // todo : add info to error message - but how to know what to write since we failed to interpret the naming source
        throw new HibernateException("Could not determine primary table name for entity");
    }
    return toIdentifier(tableName, source.getBuildingContext());
}

/**
 * The determinePrimaryTableName.
 *
 * @param entityNaming the source.
 * @return the identifier.
 */
protected String transformEntityName(EntityNaming entityNaming)
{
    // prefer the JPA entity name, if specified...
    if (StringHelper.isNotEmpty(entityNaming.getJpaEntityName()))
    {
        return entityNaming.getJpaEntityName();
    }
    else
    {
        // otherwise, use the Hibernate entity name
        return StringHelper.unqualify(entityNaming.getEntityName());
    }
}

/**
 * The determinePrimaryTableName.
 *
 * @param source the source.
 * @return the identifier.
 */
@Override
public Identifier determineJoinTableName(ImplicitJoinTableNameSource source)
{
    final String ownerPortion = source.getOwningPhysicalTableName();
    final String ownedPortion;
    if (source.getAssociationOwningAttributePath() != null)
    {
        ownedPortion = transformAttributePath(source.getAssociationOwningAttributePath());
    }
    else
    {
        ownedPortion = source.getNonOwningPhysicalTableName();
    }

    return toIdentifier(ownerPortion + "_" + ownedPortion, source.getBuildingContext());
}

/**
 * The determinePrimaryTableName.
 *
 * @param source the source.
 * @return the identifier.
 */
@Override
public Identifier determineCollectionTableName(ImplicitCollectionTableNameSource source)
{
    final String owningEntity = transformEntityName(source.getOwningEntityNaming());
    final String name = transformAttributePath(source.getOwningAttributePath());
    final String entityName;
    if (!Strings.isNullOrEmpty(owningEntity))
    {
        entityName = owningEntity + "_" + name;
    }
    else
    {
        entityName = name;
    }
    return toIdentifier(entityName, source.getBuildingContext());
}

/**
 * The determinePrimaryTableName.
 *
 * @param source the source.
 * @return the identifier.
 */
@Override
public Identifier determineIdentifierColumnName(ImplicitIdentifierColumnNameSource source)
{
    return toIdentifier(transformAttributePath(source.getIdentifierAttributePath()), source.getBuildingContext());
}

/**
 * The determinePrimaryTableName.
 *
 * @param source the source.
 * @return the identifier.
 */
@Override
public Identifier determineDiscriminatorColumnName(ImplicitDiscriminatorColumnNameSource source)
{
    return toIdentifier(
        source.getBuildingContext().getMappingDefaults().getImplicitDiscriminatorColumnName(), source.getBuildingContext());
}

/**
 * The determinePrimaryTableName.
 *
 * @param source the source.
 * @return the identifier.
 */
@Override
public Identifier determineTenantIdColumnName(ImplicitTenantIdColumnNameSource source)
{
    return toIdentifier(source.getBuildingContext().getMappingDefaults().getImplicitTenantIdColumnName(), source.getBuildingContext());
}

/**
 * The determinePrimaryTableName.
 *
 * @param source the source.
 * @return the identifier.
 */
@Override
public Identifier determineBasicColumnName(ImplicitBasicColumnNameSource source)
{
    return toIdentifier(transformAttributePath(source.getAttributePath()), source.getBuildingContext());
}

/**
 * The determineJoinColumnName.
 *
 * @param source the source.
 * @return identifier.
 */
@Override
public Identifier determineJoinColumnName(ImplicitJoinColumnNameSource source)
{
    final String name;

    if (source.getNature() == ImplicitJoinColumnNameSource.Nature.ELEMENT_COLLECTION)
    {
        name = transformEntityName(source.getEntityNaming()) + '_' + source.getReferencedColumnName().getText();
    }
    else
    {
        if (source.getAttributePath() == null)
        {
            name = source.getReferencedTableName().getText();
        }
        else
        {
            name = transformAttributePath(source.getAttributePath());
        }
    }
    return toIdentifier(name, source.getBuildingContext());
}

/**
 * The determinePrimaryTableName.
 *
 * @param source the source.
 * @return the identifier.
 */
@Override
public Identifier determinePrimaryKeyJoinColumnName(ImplicitPrimaryKeyJoinColumnNameSource source)
{
    return source.getReferencedPrimaryKeyColumnName();
}

/**
 * The determinePrimaryTableName.
 *
 * @param source the source.
 * @return the identifier.
 */
@Override
public Identifier determineAnyDiscriminatorColumnName(ImplicitAnyDiscriminatorColumnNameSource source)
{
    return toIdentifier(
        transformAttributePath(source.getAttributePath()) + "_" +
        source.getBuildingContext().getMappingDefaults().getImplicitDiscriminatorColumnName(),
        source.getBuildingContext());
}

/**
 * The determinePrimaryTableName.
 *
 * @param source the source.
 * @return the identifier.
 */
@Override
public Identifier determineAnyKeyColumnName(ImplicitAnyKeyColumnNameSource source)
{
    return toIdentifier(
        transformAttributePath(source.getAttributePath()) + "_" +
        source.getBuildingContext().getMappingDefaults().getImplicitIdColumnName(),
        source.getBuildingContext());
}

/**
 * The determinePrimaryTableName.
 *
 * @param source the source.
 * @return the identifier.
 */
@Override
public Identifier determineMapKeyColumnName(ImplicitMapKeyColumnNameSource source)
{
    return toIdentifier(
        transformAttributePath(source.getPluralAttributePath()) + "_KEY",
        source.getBuildingContext()
    );
}

/**
 * The determinePrimaryTableName.
 *
 * @param source the source.
 * @return the identifier.
 */
@Override
public Identifier determineListIndexColumnName(ImplicitIndexColumnNameSource source)
{
    return toIdentifier(transformAttributePath(source.getPluralAttributePath()) + "_ORDER", source.getBuildingContext());
}

/**
 * The determinePrimaryTableName.
 *
 * @param source the source.
 * @return the identifier.
 */
@Override
public Identifier determineForeignKeyName(ImplicitForeignKeyNameSource source)
{
    return toIdentifier(
        NamingHelper.INSTANCE.generateHashedFkName(
            "FK",
            source.getTableName(),
            source.getReferencedTableName(),
            source.getColumnNames()
        ),
        source.getBuildingContext()
    );
}

/**
 * The determinePrimaryTableName.
 *
 * @param source the source.
 * @return the identifier.
 */
@Override
public Identifier determineUniqueKeyName(ImplicitUniqueKeyNameSource source)
{
    return toIdentifier(
        NamingHelper.INSTANCE.generateHashedConstraintName(
            "UK",
            source.getTableName(),
            source.getColumnNames()
        ),
        source.getBuildingContext()
    );
}

/**
 * The determinePrimaryTableName.
 *
 * @param source the source.
 * @return the identifier.
 */
@Override
public Identifier determineIndexName(ImplicitIndexNameSource source)
{
    return toIdentifier(
        NamingHelper.INSTANCE.generateHashedConstraintName(
            "IDX",
            source.getTableName(),
            source.getColumnNames()
        ),
        source.getBuildingContext()
    );
}

/**
 * For JPA standards we typically need the unqualified name.  However, a more usable
 * impl tends to use the whole path.  This method provides an easy hook for subclasses
 * to accomplish that
 *
 * @param attributePath The attribute path
 * @return The extracted name
 */
protected String transformAttributePath(AttributePath attributePath)
{
    return attributePath.getProperty();
}

/**
 * Easy hook to build an Identifier using the keyword safe IdentifierHelper.
 *
 * @param stringForm The String form of the name
 * @param buildingContext Access to the IdentifierHelper
 * @return The identifier
 */
protected Identifier toIdentifier(String stringForm, MetadataBuildingContext buildingContext)
{

    return buildingContext.getMetadataCollector()
                          .getDatabase()
                          .getJdbcEnvironment()
                          .getIdentifierHelper()
                          .toIdentifier(stringForm);
}
}

N'joy。