1 19 20 package org.apache.avalon.excalibur.datasource.ids; 21 22 import java.math.BigDecimal ; 23 import java.sql.Connection ; 24 import java.sql.ResultSet ; 25 import java.sql.SQLException ; 26 import java.sql.Statement ; 27 28 import org.apache.avalon.framework.configuration.Configuration; 29 import org.apache.avalon.framework.configuration.ConfigurationException; 30 31 91 public class TableIdGenerator 92 extends AbstractDataSourceBlockIdGenerator 93 { 94 97 private String m_table; 98 99 102 private String m_tableName; 103 104 107 public TableIdGenerator() 108 { 109 } 110 111 114 124 private Object allocateIdBlock( int blockSize, boolean useBigDecimals ) 125 throws IdException 126 { 127 if( getLogger().isDebugEnabled() ) 128 { 129 getLogger().debug( "Allocating a new block of " + blockSize + 130 " ids for key_table " + m_tableName + "." ); 131 } 132 133 try 134 { 135 Connection conn = getConnection(); 136 try 137 { 138 boolean autoCommit = conn.getAutoCommit(); 139 140 Statement stmt = conn.createStatement(); 141 try 142 { 143 int tries = 0; 147 while( tries < 50 ) 148 { 149 String query = "SELECT next_id FROM " + m_table + " WHERE table_name = '" 151 + m_tableName + "'"; 152 ResultSet rs = stmt.executeQuery( query ); 153 if ( !rs.next() ) 154 { 155 String msg = 157 "Unable to allocate a block of Ids, no row with table_name='" 158 + m_tableName + "' exists in the " + m_table + " table."; 159 getLogger().error( msg ); 160 if ( !autoCommit ) 161 { 162 conn.rollback(); 163 } 164 165 throw new IdException( msg ); 166 } 167 168 Object nextId; 170 Object newNextId; 171 if( useBigDecimals ) 172 { 173 BigDecimal oldNextId = rs.getBigDecimal( 1 ); 174 newNextId = oldNextId.add( new BigDecimal ( blockSize ) ); 175 nextId = oldNextId; 176 } 177 else 178 { 179 long oldNextId = rs.getLong( 1 ); 180 newNextId = new Long ( oldNextId + blockSize ); 181 nextId = new Long ( oldNextId ); 182 } 183 184 try 189 { 190 query = "UPDATE " + m_table 193 + " SET next_id = '" + newNextId + "' " 194 + " WHERE table_name = '" + m_tableName + "' " 195 + " AND next_id = '" + nextId + "'"; 196 int updated = stmt.executeUpdate( query ); 197 if( updated >= 1 ) 198 { 199 if ( !autoCommit ) 201 { 202 conn.commit(); 203 } 204 205 return nextId; 207 } 208 else 209 { 210 if( getLogger().isDebugEnabled() ) 212 { 213 getLogger().debug( 214 "Update resulted in no rows being changed." ); 215 } 216 } 217 } 218 catch ( SQLException e ) 219 { 220 if( getLogger().isDebugEnabled() ) 222 { 223 getLogger().debug( 225 "Encountered an exception attempting to update the " 226 + m_table + " table. May be a transaction confict. " 227 + "Trying again: " + e.getMessage() ); 228 } 229 } 230 231 if ( !autoCommit ) 234 { 235 conn.rollback(); 236 } 237 238 tries++; 239 } 240 241 getLogger().error( "Unable to allocate a block of Ids. Too many retries." ); 243 return null; 244 } 245 finally 246 { 247 stmt.close(); 248 } 249 } 250 finally 251 { 252 conn.close(); 253 } 254 } 255 catch ( SQLException e ) 256 { 257 String msg = "Unable to allocate a block of Ids."; 258 getLogger().error( msg, e ); 259 throw new IdException( msg, e ); 260 } 261 } 262 263 266 275 protected BigDecimal allocateBigDecimalIdBlock( int blockSize ) 276 throws IdException 277 { 278 return (BigDecimal )allocateIdBlock( blockSize, true ); 279 } 280 281 290 protected long allocateLongIdBlock( int blockSize ) 291 throws IdException 292 { 293 Long id = (Long )allocateIdBlock( blockSize, false ); 294 295 return id.longValue(); 296 } 297 298 301 308 public void configure( Configuration configuration ) 309 throws ConfigurationException 310 { 311 super.configure( configuration ); 312 313 m_table = configuration.getAttribute( "table", "ids" ); 315 316 m_tableName = configuration.getAttribute( "key-table", "id" ); 318 } 319 } 320 321 | Popular Tags |