Hibernate Naming Strategie für Oracle die zweite

Vor einiger Zeit habe ich eine einfache Naming Strategie vorgestellt, die sicherstellt, dass die generierten Namen sich an die etwas geizigen Beschränkungen von Oracle hält. Ich habe die Starategie noch einmal ein wenig überarbeitet. Sie verteilt jetzt großzügiger Underscores, so dass sie mehr Stellen hat, an denen sie einen Namen kürzen kann.

Natürlich gilt wieder: Benutzung auf eigene Gefahr.

public class OracleNamingStrategy
        extends DefaultComponentSafeNamingStrategy
{

  protected static String addUnderscores(String name)
  {
    if (name == null) return null;
    StringBuffer buf = new StringBuffer(
            name.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++, '_');
      }
    }
    return buf.toString().toLowerCase();
  }

  @Override
  public String collectionTableName(String ownerEntity,
      String ownerEntityTable, String associatedEntity,
      String associatedEntityTable, String propertyName)
  {
    return abbreviateName(super.collectionTableName(
        addUnderscores(ownerEntity),
        addUnderscores(ownerEntityTable),
        addUnderscores(associatedEntity),
        addUnderscores(associatedEntityTable),
        addUnderscores(propertyName)));
  }

  @Override
  public String foreignKeyColumnName(String propertyName,
      String propertyEntityName, String propertyTableName,
      String referencedColumnName)
  {
    return abbreviateName(super.foreignKeyColumnName(
        addUnderscores(propertyName),
        addUnderscores(propertyEntityName),
        addUnderscores(propertyTableName),
        addUnderscores(referencedColumnName)));
  }

  @Override
  public String logicalCollectionColumnName(
      String columnName,
      String propertyName, String referencedColumn)
  {
    return abbreviateName(super.logicalCollectionColumnName(
        addUnderscores(columnName),
        addUnderscores(propertyName),
        addUnderscores(referencedColumn)));
  }

  @Override
  public String logicalCollectionTableName(String tableName,
      String ownerEntityTable,
      String associatedEntityTable, String propertyName)
  {
    return abbreviateName(super.logicalCollectionTableName(
        addUnderscores(tableName),
        addUnderscores(ownerEntityTable),
        addUnderscores(associatedEntityTable),
        addUnderscores(propertyName)));
  }

  @Override
  public String logicalColumnName(String columnName,
        String propertyName)
  {
    return abbreviateName(super.logicalColumnName(
        addUnderscores(columnName),
        addUnderscores(propertyName)));
  }

  @Override
  public String propertyToColumnName(String propertyName)
  {
    return abbreviateName(super.propertyToColumnName(
          addUnderscores(propertyName)));
  }

  private static final int MAX_LENGTH = 30;

  public static String abbreviateName(String someName)
  {
    if (someName.length() <= MAX_LENGTH) return someName;

    String[] tokens = splitName(someName);
    shortenName(someName, tokens);

    return assembleResults(tokens);
  }

  private static String[] splitName(String someName)
  {
    StringTokenizer toki = new StringTokenizer(someName, "_");
    String[] tokens = new String[toki.countTokens()];
    int i = 0;
    while (toki.hasMoreTokens())
    {
      tokens[i] = toki.nextToken();
      i++;
    }
    return tokens;
  }

  private static void shortenName(
       String someName, String[] tokens)
  {
    int currentLength = someName.length();
    while (currentLength > MAX_LENGTH)
    {
      int tokenIndex = getIndexOfLongest(tokens);
      String oldToken = tokens[tokenIndex];
      tokens[tokenIndex] = abbreviate(oldToken);
      currentLength -=
         oldToken.length() - tokens[tokenIndex].length();
    }
  }

  private static String assembleResults(String[] tokens)
  {
    StringBuilder result = new StringBuilder(tokens[0]);
    for (int j = 1; j < tokens.length; j++)
    {
      result.append("_").append(tokens[j]);
    }
    return result.toString();
  }

  private static String abbreviate(String token)
  {
    final String VOWELS = "AEIOUaeiou";
    boolean vowelFound = false;
    for (int i = token.length() - 1; i >= 0; i--)
    {
      if (!vowelFound)
        vowelFound = VOWELS.contains(
            String.valueOf(token.charAt(i)));
      else if (!VOWELS.contains(
            String.valueOf(token.charAt(i))))
        return token.substring(0, i + 1);
    }
    return "";
  }

  private static int getIndexOfLongest(String[] tokens)
  {
    int maxLength = 0;
    int index = -1;
    for (int i = 0; i < tokens.length; i++)
    {
      String string = tokens[i];
      if (maxLength < string.length())
      {
        maxLength = string.length();
        index = i;
      }
    }
    return index;
  }

  @Override
  public String classToTableName(String aClassName)
  {

    return abbreviateName(super.classToTableName(addUnderscores(aClassName)));
  }
}
This entry was written by Jens Schauder , posted on Saturday March 29 2008at 11:03 pm , filed under Java, Oracle . Bookmark the permalink . Post a comment below or leave a trackback: Trackback URL.

2 Responses to “Hibernate Naming Strategie für Oracle die zweite”

Leave a Reply

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>