簡體   English   中英

自動休眠索引創建時間過長

[英]Automatic Hibernate index creation too long

我回來了,現在遇到了陽光下的錯誤/問題。 通常,我在H2DB上測試本地開發和更改,但是據我所知,它也必須在Oracle和MSSQL上工作。 現在再次在oracle上進行測試會出現此問題:密鑰COR_VIEWSETTINGSCOR_USERSETTINGS_FK0和COR_VIEWSETTINGSCOR_USERSETTINGS_FK1是自動生成的,對於oracle數據庫來說太長了。 要知道如何創建這些鍵,我現在將向您顯示實體UserSettings和UserViewSettings。 提示:您可以忽略實體,如果它們使您感到困惑,則可以繼續進行編輯。 也許您仍然可以幫助我。

用戶設置

/**

      The Class UserSettings.

*/
@org.hibernate.envers.Audited
@DataObject( value =  UserSettings.DATA_OBJECT_NAME )
@CRUDDefinition( supportsRead = true, supportsCreate = true, supportsUpdate = true, supportsDelete = true )
@Entity( name = UserSettings.DATA_OBJECT_NAME )
@NamedQuery( name = UserSettings.DATA_OBJECT_NAME, query = "from userSettings e where e.name = :name" )
@javax.persistence.Inheritance( strategy = javax.persistence.InheritanceType.TABLE_PER_CLASS )
@AttributeOverrides( { @AttributeOverride( name = "id", column = @Column( name = "USERSETTINGS_ID" ) )
} )
@Table( name = "COR_USERSETTINGS", indexes = {
  @javax.persistence.Index( name="COR_USERSETTINGS_FK0", columnList = "SETTINGSTYPE_ID" ),
  @javax.persistence.Index( name="COR_USERSETTINGS_FK1", columnList = "USER_ID" ),
}
)
public class UserSettings extends NamedRevisionEntity implements NameSettingsType, NameSettings
{
  /** The Constant serialVersionUID. */
  private static final long serialVersionUID = 1L;

  /** The Constant DATA_OBJECT_NAME. */
  public static final String DATA_OBJECT_NAME = "userSettings";

  @javax.persistence.Basic( fetch = javax.persistence.FetchType.EAGER, optional = false )
  @Column( name = "SETTINGS", nullable = false, unique = false, insertable = true, updatable = true )
  @javax.persistence.Lob
  private java.lang.String settings;

  @javax.persistence.ManyToOne( fetch = javax.persistence.FetchType.EAGER, optional = false )
  @javax.persistence.JoinColumn( name = "SETTINGSTYPE_ID", nullable = false, unique = false, insertable = true, updatable = true )
  private SettingsType settingsType;

  @javax.persistence.ManyToOne( fetch = javax.persistence.FetchType.EAGER, optional = true )
  @javax.persistence.JoinColumn( name = "USER_ID", nullable = true, unique = false, insertable = true, updatable = true )
  private User user;



  public SettingsType getSettingsType()
  {
    return settingsType;
  }

  public void setSettingsType( SettingsType settingsType )
  {
    this.settingsType = settingsType;
  }

  public User getUser()
  {
    return user;
  }

  public void setUser( User user )
  {
    this.user = user;
  }

  public java.lang.String getSettings()
  {
    return settings;
  }

  public void setSettings( java.lang.String settings )
  {
    this.settings = settings;
  }

  @Override
  public String getDataObjectName()
  {
    return DATA_OBJECT_NAME;
  }



  @Override
  public String toString()
  {
    StringBuilder builder = new StringBuilder( super.toString() );

    builder.append( ", " );
    try
    {
        builder.append( ToStringUtils.referenceToString( "settingsType", "SettingsType", this.settingsType ) );
    }
    catch( Exception ex )
    {
      builder.append( ex.getClass().getName()  );
      builder.append( ": " );
      builder.append( ex.getMessage() );
    }
    builder.append( ", " );
    try
    {
        builder.append( ToStringUtils.referenceToString( "user", "User", this.user ) );
    }
    catch( Exception ex )
    {
      builder.append( ex.getClass().getName()  );
      builder.append( ": " );
      builder.append( ex.getMessage() );
    }

    builder.append( "]" );
    return builder.toString();
  }

}

UserViewSettings

/**

      The Class UserViewSettings.

*/
@org.hibernate.envers.Audited
@DataObject( value =  UserViewSettings.DATA_OBJECT_NAME )
@CRUDDefinition( supportsRead = true, supportsCreate = true, supportsUpdate = true, supportsDelete = true )
@Entity( name = UserViewSettings.DATA_OBJECT_NAME )
@AttributeOverrides( { @AttributeOverride( name = "id", column = @Column( name = "VIEWSETTINGS_ID" ) )
} )
@Table( name = "COR_VIEWSETTINGS", uniqueConstraints = {
  @javax.persistence.UniqueConstraint( name="COR_VIEWSETTINGS_UNQ1", columnNames = { "NAME", "SETTINGSTYPE_ID", "VIEW_NAME", "VIEWTYPE_ID" } ),
}
, indexes = {
  @javax.persistence.Index( name="COR_VIEWSETTINGS_FK0", columnList = "VIEWTYPE_ID" ),
}
)
public class UserViewSettings extends UserSettings implements NameViewName, NameViewType
{
  /** The Constant serialVersionUID. */
  private static final long serialVersionUID = 1L;

  /** The Constant DATA_OBJECT_NAME. */
  public static final String DATA_OBJECT_NAME = "userViewSettings";

  @javax.persistence.Basic( fetch = javax.persistence.FetchType.EAGER, optional = false )
  @Column( name = "VIEW_NAME", nullable = false, unique = false, insertable = true, updatable = true )
  private java.lang.String viewName;

  @javax.persistence.ManyToOne( fetch = javax.persistence.FetchType.EAGER, optional = true )
  @javax.persistence.JoinColumn( name = "VIEWTYPE_ID", nullable = true, unique = false, insertable = true, updatable = true )
  private ViewType viewType;



  public java.lang.String getViewName()
  {
    return viewName;
  }

  public void setViewName( java.lang.String viewName )
  {
    this.viewName = viewName;
  }

  public ViewType getViewType()
  {
    return viewType;
  }

  public void setViewType( ViewType viewType )
  {
    this.viewType = viewType;
  }

  @Override
  public String getDataObjectName()
  {
    return DATA_OBJECT_NAME;
  }



  @Override
  public String toString()
  {
    StringBuilder builder = new StringBuilder( super.toString() );

    builder.append( ", " );
    builder.append( "viewName" );
    builder.append( "=" );
    builder.append( this.viewName );
    builder.append( ", " );
    try
    {
        builder.append( ToStringUtils.referenceToString( "viewType", "ViewType", this.viewType ) );
    }
    catch( Exception ex )
    {
      builder.append( ex.getClass().getName()  );
      builder.append( ": " );
      builder.append( ex.getMessage() );
    }

    builder.append( "]" );
    return builder.toString();
  }

}

從Hibernate 5.2和Oracle 11數據庫啟動Wildfly 10.0.0會導致錯誤,即自動生成的密鑰COR_VIEWSETTINGSCOR_USERSETTINGS_FK0COR_VIEWSETTINGSCOR_USERSETTINGS_FK1對於數據庫而言太長了。

我看了一下Hibernate的NamingStrategies,甚至嘗試了一些,但是它們並沒有為我改變錯誤。

我如何影響這些密鑰的生成?

編輯:

所以打開調試給了我這個:

2016-11-29 09:22:03,190 DEBUG [org.hibernate.SQL] (ServerService Thread Pool -- 58) create index COR_USERSETTINGS_FK0 on COR_USERSETTINGS (SETTINGSTYPE_ID)
2016-11-29 09:22:03,190 DEBUG [org.hibernate.SQL] (ServerService Thread Pool -- 58) create index COR_USERSETTINGS_FK1 on COR_USERSETTINGS (USER_ID)
2016-11-29 09:22:03,190 DEBUG [org.hibernate.SQL] (ServerService Thread Pool -- 58) create index COR_VIEWSETTINGSCOR_USERSETTINGS_FK0 on COR_VIEWSETT INGS(SETTINGSTYPE_ID)
2016-11-29 09:22:03,190 DEBUG [org.hibernate.SQL] (ServerService Thread Pool -- 58) create index COR_VIEWSETTINGSCOR_USERSETTINGS_FK1 on COR_VIEWSETTINGS (USER_ID)
2016-11-29 09:22:03,190 DEBUG [org.hibernate.SQL] (ServerService Thread Pool -- 58) create index COR_VIEWSETTINGS_FK0 on COR_VIEWSETTINGS (VIEWTYPE_ID)

現在,我在org.hibernate.boot.model.naming包中找到了ImplicitIndexNameSource類,但是Internet並沒有給出我可以使用的示例,而且很長一段時間以來,它似乎一直是一個空類。

編輯2:

先前的編輯似乎是錯誤的路徑。 我找到了創建這些日志的地方。 它是從SchemaCreatorImpl調用的StandardIndexExporter 所以我需要更深入地研究框架,但是如果有人看到這一點。 這是正確的道路嗎? 我可以修改代碼以便他做我想做的事情嗎? 罪魁禍首似乎是hbm2ddl ,因為在以下行中在StandardIndexExport中創建了索引get:

final String indexNameForCreation;
if ( dialect.qualifyIndexName() ) {
    indexNameForCreation = jdbcEnvironment.getQualifiedObjectNameFormatter().format(
            new QualifiedNameImpl(
                    index.getTable().getQualifiedTableName().getCatalogName(),
                    index.getTable().getQualifiedTableName().getSchemaName(),
                    jdbcEnvironment.getIdentifierHelper().toIdentifier( index.getName() )
            ),
            jdbcEnvironment.getDialect()
    );
}
else {
    indexNameForCreation = index.getName();
}
final StringBuilder buf = new StringBuilder()
        .append( "create index " )
        .append( indexNameForCreation )
        .append( " on " )
        .append( tableName )
        .append( " (" );

boolean first = true;
Iterator<Column> columnItr = index.getColumnIterator();
while ( columnItr.hasNext() ) {
    final Column column = columnItr.next();
    if ( first ) {
        first = false;
    }
    else {
        buf.append( ", " );
    }
    buf.append( ( column.getQuotedName( dialect ) ) );
}
buf.append( ")" );
return new String[] { buf.toString() };

我將不勝感激。 這真令人沮喪

這樣我就可以了。 回答可能會發現此問題並且有相同問題的未來人們。

索引鍵由hibernate所引用的oracle方言創建。 因此,要做的是實現一個自定義OracleDialect,該自定義OracleDialect覆蓋方法getIndexExporter並指向自定義IndexExporter。 然后,您可以在此IndexExporter中修改鍵的創建方式。 就我而言,我固定了這樣的解決方案:

  /**
   * Gets the correct index name if it is a index for a TABLE_PER_CLASS inheritance and longer than
   * 30 chars.
   *
   * @param index the index to decide for
   * @return the correct index name
   */
  private String getCorrectIndexName( Index index )
  {
    if ( index.getTable() instanceof DenormalizedTable && index.getName().length() > 30 )
    {
      String prefixedTable = index.getTable().getName();
      String tableName = prefixedTable.substring( prefixedTable.indexOf( '_' ) + 1, prefixedTable.length() );
      tableName = shortenName( tableName );
      Iterator<Column> columnItr = index.getColumnIterator();
      String reference;

      if ( columnItr.hasNext() )
      {
        reference = extractReference( columnItr.next() );
      }
      else
      {
        /** backup strategy to prevent exceptions */
        reference = shortenName( NamingHelper.INSTANCE.hashedName( index.getName() ) );
      }

      return tableName + "_" + reference;
    }
    return index.getName();
  }

  /**
   * Extract the reference column of the index and hash the full name before shortening it with
   * shortenName().
   *
   * @param index the index to extract the reference from.
   * @return the reference with an appended _FK(hashedReference).
   */
  private String extractReference( Column column )
  {
    String reference = column.getQuotedName( dialect );
    String md5Hash = NamingHelper.INSTANCE.hashedName( reference );
    md5Hash = md5Hash.substring( md5Hash.length() - 4, md5Hash.length() );
    reference = shortenName( reference );

    return reference + "_FK" + md5Hash;
  }

  /**
   * Shorten the name to a maximum of 11 chars if it's longer.
   *
   * @param reference the reference to shorten
   * @return the shortened string
   */
  private static String shortenName( String reference )
  {
    if ( reference.length() > 11 )
    {
      return reference.substring( 0, 11 );
    }
    return reference;
  }

這必須在Overriden函數getSqlCreateStrings中調用 更改后的行如下所示:

  String indexName = getCorrectIndexName( index );
  indexNameForCreation = jdbcEnvironment.getQualifiedObjectNameFormatter()
      .format(
          new QualifiedNameImpl( index.getTable().getQualifiedTableName().getCatalogName(),
              index.getTable().getQualifiedTableName().getSchemaName(), jdbcEnvironment.getIdentifierHelper().toIdentifier( indexName ) ),
          jdbcEnvironment.getDialect() );

希望對您有所幫助。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM