/** * Used by subclasses to resolve deferred values on demand. This is useful when a certain value * comes from a generated key of another master object. */ protected Object getValue(Map<String, Object> valueMap, DbAttribute attribute) { Object value = valueMap.get(attribute.getName()); // if a value is a Factory, resolve it here... // slight chance that a normal value will implement Factory interface??? if (value instanceof Factory) { value = ((Factory) value).create(); valueMap.put(attribute.getName(), value); // update replacement id if (attribute.isPrimaryKey()) { // sanity check if (value == null) { String name = attribute.getEntity() != null ? attribute.getEntity().getName() : "<null>"; throw new CayenneRuntimeException( "Failed to generate PK: " + name + "." + attribute.getName()); } ObjectId id = getObjectId(); if (id != null) { // always override with fresh value as this is what's in the // DB id.getReplacementIdMap().put(attribute.getName(), value); } } } return value; }
/** * Generates a unique and non-repeating primary key for specified dbEntity. * * <p>This implementation is naive since it does not lock the database rows when executing select * and subsequent update. Adapter-specific implementations are more robust. * * @since 3.0 */ public Object generatePk(DataNode node, DbAttribute pk) throws Exception { DbEntity entity = (DbEntity) pk.getEntity(); switch (pk.getType()) { case Types.BINARY: case Types.VARBINARY: return IDUtil.pseudoUniqueSecureByteSequence(pk.getMaxLength()); } DbKeyGenerator pkGenerator = entity.getPrimaryKeyGenerator(); long cacheSize; if (pkGenerator != null && pkGenerator.getKeyCacheSize() != null) cacheSize = pkGenerator.getKeyCacheSize().intValue(); else cacheSize = pkCacheSize; long value; // if no caching, always generate fresh if (cacheSize <= 1) { value = longPkFromDatabase(node, entity); } else { synchronized (pkCache) { LongPkRange r = pkCache.get(entity.getName()); if (r == null) { // created exhausted LongPkRange r = new LongPkRange(1l, 0l); pkCache.put(entity.getName(), r); } if (r.isExhausted()) { long val = longPkFromDatabase(node, entity); r.reset(val, val + cacheSize - 1); } value = r.getNextPrimaryKey(); } } if (pk.getType() == Types.BIGINT) { return Long.valueOf(value); } else { // leaving it up to the user to ensure that PK does not exceed max int... return Integer.valueOf((int) value); } }