2015-10-13 61 views
3

我想使用hibernate 5.x.休眠5.x有ImplicitNamingStrategyPhysicalNamingStrategy的新接口。Hibernate 5 ImplicitNamingStrategy

對於屬性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; 
    } 
} 

有沒有辦法前綴與表(或實體)通過只使用一個命名的名字每列?

+0

這篇文章似乎符合您的需求:http://stackoverflow.com/questions/32165694/spring-hibernate-5-naming-strategy-configuration。 –

+0

@AndréBlaszczyk你提到的這篇文章與我的需求不符。它只是改變列名稱,但不會爲它們添加表名。 – Janning

回答

3

這裏有一個解決方案,如果你不介意有點髒反思:

@Override 
public Identifier determineBasicColumnName(final ImplicitBasicColumnNameSource source) 
{ 
    // Get 'this$0' field and make it accessible 
    Field ejb3ColumnField = null; 
    final Field[] sourceFields = source.getClass().getDeclaredFields(); 
    for (final Field sourceField : sourceFields) { 
     if (sourceField.getName().equals("this$0")) { 
      ejb3ColumnField = sourceField; 
     } 
    } 
    ejb3ColumnField.setAccessible(true); 

    // Get actual field object 
    String owningEntityName; 
    Ejb3Column ejb3Column; 
    try { 
     ejb3Column = (Ejb3Column) ejb3ColumnField.get(source); 
    } catch (
     IllegalArgumentException 
     | IllegalAccessException e) { 
     throw new RuntimeException(e); // (Or deal with this appropriately, e.g. log it.) 
    } 

    // The property holder path holds the owning entity's fully qualified name 
    final String owningEntityFullyQualifiedName = ejb3Column.getPropertyHolder().getPath(); 

    // The entity name is after the last dot in the fully qualified name 
    final String[] owningEntityTokens = owningEntityFullyQualifiedName.split("\\."); 
    owningEntityName = owningEntityTokens[owningEntityTokens.length - 1]; 

    final Identifier basicColumnName = super.determineBasicColumnName(source); 
    return Identifier.toIdentifier(owningEntityName + "_" + basicColumnName.toString()); 
} 
3

這是基於史蒂夫錢伯斯回答我的最終解決方案。這個解決方案甚至考慮了帶註釋的明確命名並修復了連接列名。但史蒂夫應該得到所有優點他的回答

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

我實現了兩個接口,讓99.99%的結果冬眠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 。

相關問題