| CODENOTIFIER | HelpYou are not signed inSign in |
Project: Hibernate
Revision: 15145
Author: steve.ebersole@jboss.com
Date: 29 Aug 2008 02:22:52
Changes:HHH-2686 : enhanced.TableGenerator - generator table PK;
HHH-3231 : enhanced.TableGenerator - improper SELECT ... FOR UPDATE OF building;
HHH-3249 : enhanced.TableGenerator - extensibility;
HHH-3454 : enhanced.TableGenerator - allow segment value default to be the entity table name
| ... | ...@@ -31,6 +31,8 @@ | |
| 31 | 31 | import java.sql.ResultSet; |
| 32 | 32 | import java.util.Properties; |
| 33 | 33 | import java.util.HashMap; |
| 34 | import java.util.Collections; | |
| 35 | import java.util.Map; | |
| 34 | 36 | import java.io.Serializable; |
| 35 | 37 | |
| 36 | 38 | import org.slf4j.Logger; |
| ... | ...@@ -49,17 +51,29 @@ | |
| 49 | 51 | import org.hibernate.mapping.Table; |
| 50 | 52 | import org.hibernate.util.PropertiesHelper; |
| 51 | 53 | import org.hibernate.util.StringHelper; |
| 52 | import org.hibernate.util.CollectionHelper; | |
| 53 | 54 | |
| 54 | 55 | /** |
| 55 | * An enhanced version of explicit table-based generator. The main basis | |
| 56 | * conceptualization is similiar to the legacy | |
| 56 | * An enhanced version of table-based id generation. | |
| 57 | * <p/> | |
| 58 | * Unlike the simplistic legacy one (which, btw, was only ever intended for subclassing | |
| 59 | * support) we "segment" the table into multiple values. Thus a single table can | |
| 60 | * actually serve as the persistent storage for multiple independent generators. One | |
| 61 | * approach would be to segment the values by the name of the entity for which we are | |
| 62 | * performing generation, which would mean that we would have a row in the generator | |
| 63 | * table for each entity name. Or any configuration really; the setup is very flexible. | |
| 64 | * <p/> | |
| 65 | * In this respect it is very simliar to the legacy | |
| 57 | 66 | * {@link org.hibernate.id.MultipleHiLoPerTableGenerator} in terms of the |
| 58 | 67 | * underlying storage structure (namely a single table capable of holding |
| 59 | 68 | * multiple generator values). The differentiator is, as with |
| 60 | * {@link SequenceStyleGenerator} as well, the externalization of the notion | |
| 69 | * {@link SequenceStyleGenerator} as well, the externalized notion | |
| 61 | 70 | * of an optimizer. |
| 62 | 71 | * <p/> |
| 72 | * <b>NOTE</b> that by default we use a single row for all genertators (based | |
| 73 | * on {@link #DEF_SEGMENT_VALUE}). The configuration parameter | |
| 74 | * {@link #CONFIG_PREFER_SEGMENT_PER_ENTITY} can be used to change that to | |
| 75 | * instead default to using a row for each entity name. | |
| 76 | * <p/> | |
| 63 | 77 | * Configuration parameters: |
| 64 | 78 | * <table> |
| 65 | 79 | * <tr> |
| ... | ...@@ -114,6 +128,8 @@ | |
| 114 | 128 | public class TableGenerator extends TransactionHelper implements PersistentIdentifierGenerator, Configurable { |
| 115 | 129 | private static final Logger log = LoggerFactory.getLogger( TableGenerator.class ); |
| 116 | 130 | |
| 131 | public static final String CONFIG_PREFER_SEGMENT_PER_ENTITY = "hibernate.id.enhanced.table.prefer_segment_per_entity"; | |
| 132 | ||
| 117 | 133 | public static final String TABLE_PARAM = "table_name"; |
| 118 | 134 | public static final String DEF_TABLE = "hibernate_sequences"; |
| 119 | 135 | |
| ... | ...@@ -138,101 +154,281 @@ | |
| 138 | 154 | public static final String OPT_PARAM = "optimizer"; |
| 139 | 155 | |
| 140 | 156 | |
| 157 | private Type identifierType; | |
| 158 | ||
| 141 | 159 | private String tableName; |
| 142 | private String valueColumnName; | |
| 160 | ||
| 143 | 161 | private String segmentColumnName; |
| 144 | 162 | private String segmentValue; |
| 145 | 163 | private int segmentValueLength; |
| 164 | ||
| 165 | private String valueColumnName; | |
| 146 | 166 | private int initialValue; |
| 147 | 167 | private int incrementSize; |
| 148 | 168 | |
| 149 | private Type identifierType; | |
| 150 | ||
| 151 | private String query; | |
| 152 | private String insert; | |
| 153 | private String update; | |
| 169 | private String selectQuery; | |
| 170 | private String insertQuery; | |
| 171 | private String updateQuery; | |
| 154 | 172 | |
| 155 | 173 | private Optimizer optimizer; |
| 156 | 174 | private long accessCount = 0; |
| 157 | 175 | |
| 158 | public String getTableName() { | |
| 176 | /** | |
| 177 | * {@inheritDoc} | |
| 178 | */ | |
| 179 | public Object generatorKey() { | |
| 159 | 180 | return tableName; |
| 160 | 181 | } |
| 161 | 182 | |
| 162 | public String getSegmentColumnName() { | |
| 183 | /** | |
| 184 | * Type mapping for the identifier. | |
| 185 | * | |
| 186 | * @return The identifier type mapping. | |
| 187 | */ | |
| 188 | public final Type getIdentifierType() { | |
| 189 | return identifierType; | |
| 190 | } | |
| 191 | ||
| 192 | /** | |
| 193 | * The name of the table in which we store this generator's persistent state. | |
| 194 | * | |
| 195 | * @return The table name. | |
| 196 | */ | |
| 197 | public final String getTableName() { | |
| 198 | return tableName; | |
| 199 | } | |
| 200 | ||
| 201 | /** | |
| 202 | * The name of the column in which we store the segment to which each row | |
| 203 | * belongs. The value here acts as PK. | |
| 204 | * | |
| 205 | * @return The segment column name | |
| 206 | */ | |
| 207 | public final String getSegmentColumnName() { | |
| 163 | 208 | return segmentColumnName; |
| 164 | 209 | } |
| 165 | 210 | |
| 166 | public String getSegmentValue() { | |
| 211 | /** | |
| 212 | * The value in {@link #getSegmentColumnName segment column} which | |
| 213 | * corresponding to this generator instance. In other words this value | |
| 214 | * indicates the row in which this generator instance will store values. | |
| 215 | * | |
| 216 | * @return The segment value for this generator instance. | |
| 217 | */ | |
| 218 | public final String getSegmentValue() { | |
| 167 | 219 | return segmentValue; |
| 168 | 220 | } |
| 169 | 221 | |
| 170 | public int getSegmentValueLength() { | |
| 222 | /** | |
| 223 | * The size of the {@link #getSegmentColumnName segment column} in the | |
| 224 | * underlying table. | |
| 225 | * <p/> | |
| 226 | * <b>NOTE</b> : should really have been called 'segmentColumnLength' or | |
| 227 | * even better 'segmentColumnSize' | |
| 228 | * | |
| 229 | * @return the column size. | |
| 230 | */ | |
| 231 | public final int getSegmentValueLength() { | |
| 171 | 232 | return segmentValueLength; |
| 172 | 233 | } |
| 173 | 234 | |
| 174 | public String getValueColumnName() { | |
| 235 | /** | |
| 236 | * The name of the column in which we store our persistent generator value. | |
| 237 | * | |
| 238 | * @return The name of the value column. | |
| 239 | */ | |
| 240 | public final String getValueColumnName() { | |
| 175 | 241 | return valueColumnName; |
| 176 | 242 | } |
| 177 | 243 | |
| 178 | public Type getIdentifierType() { | |
| 179 | return identifierType; | |
| 180 | } | |
| 181 | ||
| 182 | public int getInitialValue() { | |
| 244 | /** | |
| 245 | * The initial value to use when we find no previous state in the | |
| 246 | * generator table corresponding to our sequence. | |
| 247 | * | |
| 248 | * @return The initial value to use. | |
| 249 | */ | |
| 250 | public final int getInitialValue() { | |
| 183 | 251 | return initialValue; |
| 184 | 252 | } |
| 185 | 253 | |
| 186 | public int getIncrementSize() { | |
| 254 | /** | |
| 255 | * The amount of increment to use. The exact implications of this | |
| 256 | * depends on the {@link #getOptimizer() optimizer} being used. | |
| 257 | * | |
| 258 | * @return The increment amount. | |
| 259 | */ | |
| 260 | public final int getIncrementSize() { | |
| 187 | 261 | return incrementSize; |
| 188 | 262 | } |
| 189 | 263 | |
| 190 | public Optimizer getOptimizer() { | |
| 264 | /** | |
| 265 | * The optimizer being used by this generator. | |
| 266 | * | |
| 267 | * @return Out optimizer. | |
| 268 | */ | |
| 269 | public final Optimizer getOptimizer() { | |
| 191 | 270 | return optimizer; |
| 192 | 271 | } |
| 193 | 272 | |
| 194 | public long getTableAccessCount() { | |
| 273 | /** | |
| 274 | * Getter for property 'tableAccessCount'. Only really useful for unit test | |
| 275 | * assertions. | |
| 276 | * | |
| 277 | * @return Value for property 'tableAccessCount'. | |
| 278 | */ | |
| 279 | public final long getTableAccessCount() { | |
| 195 | 280 | return accessCount; |
| 196 | 281 | } |
| 197 | 282 | |
| 283 | /** | |
| 284 | * {@inheritDoc} | |
| 285 | */ | |
| 198 | 286 | public void configure(Type type, Properties params, Dialect dialect) throws MappingException { |
| 199 | tableName = PropertiesHelper.getString( TABLE_PARAM, params, DEF_TABLE ); | |
| 200 | if ( tableName.indexOf( '.' ) < 0 ) { | |
| 287 | identifierType = type; | |
| 288 | ||
| 289 | tableName = determneGeneratorTableName( params ); | |
| 290 | segmentColumnName = determineSegmentColumnName( params ); | |
| 291 | valueColumnName = determineValueColumnName( params ); | |
| 292 | ||
| 293 | segmentValue = determineSegmentValue( params ); | |
| 294 | ||
| 295 | segmentValueLength = determineSegmentColumnSize( params ); | |
| 296 | initialValue = determineInitialValue( params ); | |
| 297 | incrementSize = determineIncrementSize( params ); | |
| 298 | ||
| 299 | this.selectQuery = buildSelectQuery( dialect ); | |
| 300 | this.updateQuery = buildUpdateQuery(); | |
| 301 | this.insertQuery = buildInsertQuery(); | |
| 302 | ||
| 303 | String defOptStrategy = incrementSize <= 1 ? OptimizerFactory.NONE : OptimizerFactory.POOL; | |
| 304 | String optimizationStrategy = PropertiesHelper.getString( OPT_PARAM, params, defOptStrategy ); | |
| 305 | optimizer = OptimizerFactory.buildOptimizer( optimizationStrategy, identifierType.getReturnedClass(), incrementSize ); | |
| 306 | } | |
| 307 | ||
| 308 | /** | |
| 309 | * Determine the table name to use for the generator values. | |
| 310 | * <p/> | |
| 311 | * Called during {@link #configure configuration}. | |
| 312 | * | |
| 313 | * @see #getTableName() | |
| 314 | * @param params The params supplied in the generator config (plus some standard useful extras). | |
| 315 | * @return The table name to use. | |
| 316 | */ | |
| 317 | protected String determneGeneratorTableName(Properties params) { | |
| 318 | String name = PropertiesHelper.getString( TABLE_PARAM, params, DEF_TABLE ); | |
| 319 | boolean isGivenNameUnqualified = name.indexOf( '.' ) < 0; | |
| 320 | if ( isGivenNameUnqualified ) { | |
| 321 | // if the given name is un-qualified we may neen to qualify it | |
| 201 | 322 | String schemaName = params.getProperty( SCHEMA ); |
| 202 | 323 | String catalogName = params.getProperty( CATALOG ); |
| 203 | tableName = Table.qualify( catalogName, schemaName, tableName ); | |
| 324 | name = Table.qualify( catalogName, schemaName, name ); | |
| 204 | 325 | } |
| 326 | return name; | |
| 327 | } | |
| 205 | 328 | |
| 206 | segmentColumnName = PropertiesHelper.getString( SEGMENT_COLUMN_PARAM, params, DEF_SEGMENT_COLUMN ); | |
| 207 | segmentValue = params.getProperty( SEGMENT_VALUE_PARAM ); | |
| 329 | /** | |
| 330 | * Determine the name of the column used to indicate the segment for each | |
| 331 | * row. This column acts as the primary key. | |
| 332 | * <p/> | |
| 333 | * Called during {@link #configure configuration}. | |
| 334 | * | |
| 335 | * @see #getSegmentColumnName() | |
| 336 | * @param params The params supplied in the generator config (plus some standard useful extras). | |
| 337 | * @return The name of the segment column | |
| 338 | */ | |
| 339 | protected String determineSegmentColumnName(Properties params) { | |
| 340 | return PropertiesHelper.getString( SEGMENT_COLUMN_PARAM, params, DEF_SEGMENT_COLUMN ); | |
| 341 | } | |
| 342 | ||
| 343 | /** | |
| 344 | * Determine the name of the column in which we will store the generator persistent value. | |
| 345 | * <p/> | |
| 346 | * Called during {@link #configure configuration}. | |
| 347 | * | |
| 348 | * @see #getValueColumnName() | |
| 349 | * @param params The params supplied in the generator config (plus some standard useful extras). | |
| 350 | * @return The name of the value column | |
| 351 | */ | |
| 352 | protected String determineValueColumnName(Properties params) { | |
| 353 | return PropertiesHelper.getString( VALUE_COLUMN_PARAM, params, DEF_VALUE_COLUMN ); | |
| 354 | } | |
| 355 | ||
| 356 | /** | |
| 357 | * Determine the segment value corresponding to this generator instance. | |
| 358 | * <p/> | |
| 359 | * Called during {@link #configure configuration}. | |
| 360 | * | |
| 361 | * @see #getSegmentValue() | |
| 362 | * @param params The params supplied in the generator config (plus some standard useful extras). | |
| 363 | * @return The name of the value column | |
| 364 | */ | |
| 365 | protected String determineSegmentValue(Properties params) { | |
| 366 | String segmentValue = params.getProperty( SEGMENT_VALUE_PARAM ); | |
| 208 | 367 | if ( StringHelper.isEmpty( segmentValue ) ) { |
| 209 | log.debug( "explicit segment value for id generator [" + tableName + '.' + segmentColumnName + "] suggested; using default [" + DEF_SEGMENT_VALUE + "]" ); | |
| 210 | segmentValue = DEF_SEGMENT_VALUE; | |
| 368 | segmentValue = determineDefaultSegmentValue( params ); | |
| 211 | 369 | } |
| 212 | segmentValueLength = PropertiesHelper.getInt( SEGMENT_LENGTH_PARAM, params, DEF_SEGMENT_LENGTH ); | |
| 213 | valueColumnName = PropertiesHelper.getString( VALUE_COLUMN_PARAM, params, DEF_VALUE_COLUMN ); | |
| 214 | initialValue = PropertiesHelper.getInt( INITIAL_PARAM, params, DEFAULT_INITIAL_VALUE ); | |
| 215 | incrementSize = PropertiesHelper.getInt( INCREMENT_PARAM, params, DEFAULT_INCREMENT_SIZE ); | |
| 216 | identifierType = type; | |
| 370 | return segmentValue; | |
| 371 | } | |
| 217 | 372 | |
| 218 | String query = "select " + valueColumnName + | |
| 219 | " from " + tableName + " tbl" + | |
| 220 | " where tbl." + segmentColumnName + "=?"; | |
| 373 | /** | |
| 374 | * Used in the cases where {@link #determineSegmentValue} is unable to | |
| 375 | * determine the value to use. | |
| 376 | * | |
| 377 | * @param params The params supplied in the generator config (plus some standard useful extras). | |
| 378 | * @return The default segment value to use. | |
| 379 | */ | |
| 380 | protected String determineDefaultSegmentValue(Properties params) { | |
| 381 | boolean preferSegmentPerEntity = PropertiesHelper.getBoolean( CONFIG_PREFER_SEGMENT_PER_ENTITY, params, false ); | |
| 382 | String defaultToUse = preferSegmentPerEntity ? params.getProperty( TABLE ) : DEF_SEGMENT_VALUE; | |
| 383 | log.info( "explicit segment value for id generator [" + tableName + '.' + segmentColumnName + "] suggested; using default [" + defaultToUse + "]" ); | |
| 384 | return defaultToUse; | |
| 385 | } | |
| 386 | ||
| 387 | /** | |
| 388 | * Determine the size of the {@link #getSegmentColumnName segment column} | |
| 389 | * <p/> | |
| 390 | * Called during {@link #configure configuration}. | |
| 391 | * | |
| 392 | * @see #getSegmentValueLength() | |
| 393 | * @param params The params supplied in the generator config (plus some standard useful extras). | |
| 394 | * @return The size of the segment column | |
| 395 | */ | |
| 396 | protected int determineSegmentColumnSize(Properties params) { | |
| 397 | return PropertiesHelper.getInt( SEGMENT_LENGTH_PARAM, params, DEF_SEGMENT_LENGTH ); | |
| 398 | } | |
| 399 | ||
| 400 | protected int determineInitialValue(Properties params) { | |
| 401 | return PropertiesHelper.getInt( INITIAL_PARAM, params, DEFAULT_INITIAL_VALUE ); | |
| 402 | } | |
| 403 | ||
| 404 | protected int determineIncrementSize(Properties params) { | |
| 405 | return PropertiesHelper.getInt( INCREMENT_PARAM, params, DEFAULT_INCREMENT_SIZE ); | |
| 406 | } | |
| 407 | ||
| 408 | protected String buildSelectQuery(Dialect dialect) { | |
| 409 | final String alias = "tbl"; | |
| 410 | String query = "select " + StringHelper.qualify( alias, valueColumnName ) + | |
| 411 | " from " + tableName + ' ' + alias + | |
| 412 | " where " + StringHelper.qualify( alias, segmentColumnName ) + "=?"; | |
| 221 | 413 | HashMap lockMap = new HashMap(); |
| 222 | lockMap.put( "tbl", LockMode.UPGRADE ); | |
| 223 | this.query = dialect.applyLocksToSql( query, lockMap, CollectionHelper.EMPTY_MAP ); | |
| 414 | lockMap.put( alias, LockMode.UPGRADE ); | |
| 415 | Map updateTargetColumnsMap = Collections.singletonMap( alias, new String[] { valueColumnName } ); | |
| 416 | return dialect.applyLocksToSql( query, lockMap, updateTargetColumnsMap ); | |
| 417 | } | |
| 224 | 418 | |
| 225 | update = "update " + tableName + | |
| 419 | protected String buildUpdateQuery() { | |
| 420 | return "update " + tableName + | |
| 226 | 421 | " set " + valueColumnName + "=? " + |
| 227 | 422 | " where " + valueColumnName + "=? and " + segmentColumnName + "=?"; |
| 423 | } | |
| 228 | 424 | |
| 229 | insert = "insert into " + tableName + " (" + segmentColumnName + ", " + valueColumnName + ") " + " values (?,?)"; | |
| 230 | ||
| 231 | String defOptStrategy = incrementSize <= 1 ? OptimizerFactory.NONE : OptimizerFactory.POOL; | |
| 232 | String optimizationStrategy = PropertiesHelper.getString( OPT_PARAM, params, defOptStrategy ); | |
| 233 | optimizer = OptimizerFactory.buildOptimizer( optimizationStrategy, identifierType.getReturnedClass(), incrementSize ); | |
| 425 | protected String buildInsertQuery() { | |
| 426 | return "insert into " + tableName + " (" + segmentColumnName + ", " + valueColumnName + ") " + " values (?,?)"; | |
| 234 | 427 | } |
| 235 | 428 | |
| 429 | /** | |
| 430 | * {@inheritDoc} | |
| 431 | */ | |
| 236 | 432 | public synchronized Serializable generate(final SessionImplementor session, Object obj) { |
| 237 | 433 | return optimizer.generate( |
| 238 | 434 | new AccessCallback() { |
| ... | ...@@ -243,23 +439,24 @@ | |
| 243 | 439 | ); |
| 244 | 440 | } |
| 245 | 441 | |
| 442 | /** | |
| 443 | * {@inheritDoc} | |
| 444 | */ | |
| 246 | 445 | public Serializable doWorkInCurrentTransaction(Connection conn, String sql) throws SQLException { |
| 247 | 446 | int result; |
| 248 | 447 | int rows; |
| 249 | 448 | do { |
| 250 | sql = query; | |
| 251 | SQL_STATEMENT_LOGGER.logStatement( sql, FormatStyle.BASIC ); | |
| 252 | PreparedStatement queryPS = conn.prepareStatement( query ); | |
| 449 | SQL_STATEMENT_LOGGER.logStatement( selectQuery, FormatStyle.BASIC ); | |
| 450 | PreparedStatement selectPS = conn.prepareStatement( selectQuery ); | |
| 253 | 451 | try { |
| 254 | queryPS.setString( 1, segmentValue ); | |
| 255 | ResultSet queryRS = queryPS.executeQuery(); | |
| 256 | if ( !queryRS.next() ) { | |
| 452 | selectPS.setString( 1, segmentValue ); | |
| 453 | ResultSet selectRS = selectPS.executeQuery(); | |
| 454 | if ( !selectRS.next() ) { | |
| 257 | 455 | PreparedStatement insertPS = null; |
| 258 | 456 | try { |
| 259 | 457 | result = initialValue; |
| 260 | sql = insert; | |
| 261 | SQL_STATEMENT_LOGGER.logStatement( sql, FormatStyle.BASIC ); | |
| 262 | insertPS = conn.prepareStatement( insert ); | |
| 458 | SQL_STATEMENT_LOGGER.logStatement( insertQuery, FormatStyle.BASIC ); | |
| 459 | insertPS = conn.prepareStatement( insertQuery ); | |
| 263 | 460 | insertPS.setString( 1, segmentValue ); |
| 264 | 461 | insertPS.setLong( 2, result ); |
| 265 | 462 | insertPS.execute(); |
| ... | ...@@ -271,21 +468,20 @@ | |
| 271 | 468 | } |
| 272 | 469 | } |
| 273 | 470 | else { |
| 274 | result = queryRS.getInt( 1 ); | |
| 471 | result = selectRS.getInt( 1 ); | |
| 275 | 472 | } |
| 276 | queryRS.close(); | |
| 473 | selectRS.close(); | |
| 277 | 474 | } |
| 278 | 475 | catch ( SQLException sqle ) { |
| 279 | 476 | log.error( "could not read or init a hi value", sqle ); |
| 280 | 477 | throw sqle; |
| 281 | 478 | } |
| 282 | 479 | finally { |
| 283 | queryPS.close(); | |
| 480 | selectPS.close(); | |
| 284 | 481 | } |
| 285 | 482 | |
| 286 | sql = update; | |
| 287 | SQL_STATEMENT_LOGGER.logStatement( sql, FormatStyle.BASIC ); | |
| 288 | PreparedStatement updatePS = conn.prepareStatement( update ); | |
| 483 | SQL_STATEMENT_LOGGER.logStatement( updateQuery, FormatStyle.BASIC ); | |
| 484 | PreparedStatement updatePS = conn.prepareStatement( updateQuery ); | |
| 289 | 485 | try { |
| 290 | 486 | long newValue = optimizer.applyIncrementSizeToSourceValues() |
| 291 | 487 | ? result + incrementSize : result + 1; |
| ... | ...@@ -295,7 +491,7 @@ | |
| 295 | 491 | rows = updatePS.executeUpdate(); |
| 296 | 492 | } |
| 297 | 493 | catch ( SQLException sqle ) { |
| 298 | log.error( "could not update hi value in: " + tableName, sqle ); | |
| 494 | log.error( "could not updateQuery hi value in: " + tableName, sqle ); | |
| 299 | 495 | throw sqle; |
| 300 | 496 | } |
| 301 | 497 | finally { |
| ... | ...@@ -309,6 +505,9 @@ | |
| 309 | 505 | return new Integer( result ); |
| 310 | 506 | } |
| 311 | 507 | |
| 508 | /** | |
| 509 | * {@inheritDoc} | |
| 510 | */ | |
| 312 | 511 | public String[] sqlCreateStrings(Dialect dialect) throws HibernateException { |
| 313 | 512 | return new String[] { |
| 314 | 513 | new StringBuffer() |
| ... | ...@@ -323,11 +522,16 @@ | |
| 323 | 522 | .append( valueColumnName ) |
| 324 | 523 | .append( ' ' ) |
| 325 | 524 | .append( dialect.getTypeName( Types.BIGINT ) ) |
| 326 | .append( " ) " ) | |
| 525 | .append( ", primary key ( " ) | |
| 526 | .append( segmentColumnName ) | |
| 527 | .append( " ) ) " ) | |
| 327 | 528 | .toString() |
| 328 | 529 | }; |
| 329 | 530 | } |
| 330 | 531 | |
| 532 | /** | |
| 533 | * {@inheritDoc} | |
| 534 | */ | |
| 331 | 535 | public String[] sqlDropStrings(Dialect dialect) throws HibernateException { |
| 332 | 536 | StringBuffer sqlDropString = new StringBuffer().append( "drop table " ); |
| 333 | 537 | if ( dialect.supportsIfExistsBeforeTableName() ) { |
| ... | ...@@ -339,8 +543,4 @@ | |
| 339 | 543 | } |
| 340 | 544 | return new String[] { sqlDropString.toString() }; |
| 341 | 545 | } |
| 342 | ||
| 343 | public Object generatorKey() { | |
| 344 | return tableName; | |
| 345 | } | |
| 346 | 546 | } |