Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
   /*
    * Copyright 2007 Daniel Spiewak
    * 
    * Licensed under the Apache License, Version 2.0 (the "License"); 
    * you may not use this file except in compliance with the License. 
    * You may obtain a copy of the License at
    * 
    *	    http://www.apache.org/licenses/LICENSE-2.0 
    * 
   * Unless required by applicable law or agreed to in writing, software 
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  package net.java.ao;
  
  
  import java.util.HashMap;
  import java.util.List;
  import java.util.Map;
  import java.util.Set;
  
  import static net.java.ao.Common.getAttributeTypeFromMethod;
  import static net.java.ao.Common.preloadValue;
  import static net.java.ao.Common.where;
  import static net.java.ao.sql.SqlUtils.closeQuietly;

Author(s):
Daniel Spiewak
  
  public class EntityProxy<T extends RawEntity<K>, K> implements InvocationHandler
  {
      static boolean ignorePreload = false;	// hack for testing
  	
  	private final K key;
  	private final EntityInfo<T, K> entityInfo;
  
  	private final EntityManager manager;
  	
  	private CacheLayer layer;
  	
  	private Map<StringReadWriteLocklocks;
  	private final ReadWriteLock locksLock = new ReentrantReadWriteLock();
  	
  
  	EntityProxy(EntityManager managerEntityInfo<T, K> entityInfo, K key) {
  		this. = key;
  		this. = entityInfo;
  		this. = manager;
  		
  		 = new HashMap<StringReadWriteLock>();
  	}
  
      {
          return .getNameConverters().getFieldNameConverter();
      }
  
      @SuppressWarnings("unchecked")
  	public Object invoke(final Object proxyfinal Method methodfinal Object[] argsthrows Throwable {
          final String methodName = method.getName();
  
          if(methodName.equals("getEntityProxy")) {
              return this;
          }
  
  		if (methodName.equals("getEntityType")) {
  			return getType();
  		}
  
  		if ( == null) {
 			.init((T) proxy);
 		}
 
 		final MethodImplWrapper methodImpl = .getMethod(methodNamemethod.getParameterTypes());
 		if (methodImpl != null) {
 			final Class<?> declaringClass = methodImpl.getMethod().getDeclaringClass();
 			if (!Object.class.equals(declaringClass)) {
                 // We don't want to return get the class Class using Class.forName as this doesn't play well
                 // with multiple ClassLoaders (if the AO library has a separate class loader to the AO client)
                 // Instead just compare the classNames
 				final String callingClassName = Common.getCallingClassName(1);
 				if (callingClassName == null || !callingClassName.equals(declaringClass.getName())) {
 					return methodImpl.getMethod().invoke(methodImpl.getInstance(), args);
 				}
 			}
 		}
 
 			return getKey();
 		}
         if (methodName.equals("save")) {
 			save((RawEntity<K>) proxy);
 			return .;
 		}
         if (methodName.equals("getEntityManager")) {
             return ;
         }
         if (methodName.equals("addPropertyChangeListener")) {
 			return null;
 		}
         if (methodName.equals("removePropertyChangeListener")) {
 			return null;
 		}
         if (methodName.equals("hashCode")) {
 			return hashCodeImpl();
 		}
         if (methodName.equals("equals")) {
 			return equalsImpl((RawEntity<K>) proxyargs[0]);
 		}
         if (methodName.equals("toString")) {
 			return toStringImpl();
 		}
         if (methodName.equals("init")) {
 			return null;
 		}
 
         final FieldInfo fieldInfo = .getField(method);
 
         if (fieldInfo != null && !fieldInfo.isNullable() && args != null && args.length > 0) {
             if (args[0] == null) {
                 throw new IllegalArgumentException("Field '" + getFieldNameConverter().getName(method) + "' does not accept null values");
             }
         }
 
         // TODO move this information into EntityInfo and friends
         final OneToOne oneToOneAnnotation = method.getAnnotation(OneToOne.class);
         if (oneToOneAnnotation != null && RawEntity.class.isAssignableFrom(method.getReturnType())) {
             if (oneToOneAnnotation.reverse().isEmpty()) {
                 return legacyFetchOneToOne((RawEntity<K>) proxymethodoneToOneAnnotation);
             } else {
                 return fetchOneToOne(methodoneToOneAnnotation);
             }
 		}
 
         // TODO move this information into EntityInfo and friends
         final OneToMany oneToManyAnnotation = method.getAnnotation(OneToMany.class);
         if (oneToManyAnnotation != null && method.getReturnType().isArray()
             if (oneToManyAnnotation.reverse().isEmpty()) {
                 return legacyFetchOneToMany((RawEntity<K>) proxymethodoneToManyAnnotation);
             } else {
                 return fetchOneToMany(methodoneToManyAnnotation);
             }
 		}
 
         // TODO move this information into EntityInfo and friends
         final ManyToMany manyToManyAnnotation = method.getAnnotation(ManyToMany.class);
         if (manyToManyAnnotation != null && method.getReturnType().isArray()
             if (manyToManyAnnotation.reverse().isEmpty() || manyToManyAnnotation.through().isEmpty()) {
                 return legacyFetchManyToMany((RawEntity<K>) proxymethodmanyToManyAnnotation);
             } else {
                 return fetchManyToMany(methodmanyToManyAnnotation);
             }
 		}
 
         if (fieldInfo != null) {
 
             if (method.equals(fieldInfo.getAccessor())) {
                 return invokeGetter((RawEntity<?>) proxyfieldInfo);
             }
 
             if (method.equals(fieldInfo.getMutator())) {
                 invokeSetter((T) proxygetFieldNameConverter().getName(method), args[0], fieldInfo.getPolymorphicName());
                 return .;
             }
         }
 
 		throw new IllegalArgumentException("Cannot handle method. It is not a valid getter or setter and does not have an implementation supplied. " +
                 "Signature: " + method.toString());
 	}
 
     private RawEntity[] fetchManyToMany(final Method methodfinal ManyToMany annotationthrows SQLExceptionNoSuchMethodException
     {
         final Class remoteType = method.getReturnType().getComponentType();
         final Class throughType = annotation.value();
         final String whereClause = Common.where(annotationgetFieldNameConverter());
         final Preload preloadAnnotation = (PreloadremoteType.getAnnotation(Preload.class);
         final Method reverseMethod = throughType.getMethod(annotation.reverse());
         final Method throughMethod = throughType.getMethod(annotation.through());
         final String reversePolymorphicTypeFieldName = getAttributeTypeFromMethod(reverseMethod).isAnnotationPresent(Polymorphic.class) ? getFieldNameConverter().getPolyTypeName(reverseMethod) : null;
         final String remotePolymorphicTypeFieldName = getAttributeTypeFromMethod(throughMethod).isAnnotationPresent(Polymorphic.class) ? getFieldNameConverter().getPolyTypeName(throughMethod) : null;
         final String returnField = getFieldNameConverter().getName(throughMethod);
         final Set<StringselectFields = new LinkedHashSet<String>();
         final DatabaseProvider provider = .getProvider();
         final StringBuilder sql = new StringBuilder("SELECT t.").append(provider.processID(returnField));
         if (remotePolymorphicTypeFieldName != null)
         {
             sql.append(", t.").append(provider.processID(remotePolymorphicTypeFieldName));
         }
         if (preloadAnnotation != null && !) {
             selectFields.addAll(preloadValue(preloadAnnotationgetFieldNameConverter()));
             if (selectFields.contains(.)) {
                 sql.append(", r.*");
             } else {
                 for (final String field : selectFields) {
                     sql.append(", r.").append(.getProvider().processID(field));
                 }
             }
         }
         final String throughTable = provider.withSchema(getTableNameConverter().getName(throughType));
         sql.append(" FROM ").append(throughTable).append(" t ");
         final String remotePrimaryKeyField = Common.getPrimaryKeyField(remoteTypegetFieldNameConverter());
         if (preloadAnnotation != null) {
             final String remoteTable = provider.withSchema(getTableNameConverter().getName(remoteType));
             sql.append(" INNER JOIN ").append(remoteTable).append(" r ON t.").append(provider.processID(returnField)).append(" = r.").append(provider.processID(remotePrimaryKeyField));
         }
         final String reverseField = provider.processID(getFieldNameConverter().getName(reverseMethod));
         sql.append(" WHERE ");
         if (preloadAnnotation != null) {
             sql.append("t.");
         }
         sql.append(reverseField).append(" = ?");
         if (reversePolymorphicTypeFieldName != null)
         {
             sql.append(" AND ");
             if (preloadAnnotation != null) {
                 sql.append("t.");
             }
             sql.append(provider.processID(reversePolymorphicTypeFieldName)).append(" = ?");
         }
         if (!whereClause.trim().equals(""))
         {
             sql.append(" AND (").append(provider.processWhereClause(whereClause)).append(")");
         }
         final List<RawEntityback = new ArrayList<RawEntity>();
         final Connection conn = provider.getConnection();
         try
         {
             final PreparedStatement stmt = provider.preparedStatement(connsql);
             try
             {
                 final TypeInfo<K> dbType = getTypeManager().getType(getClass());
                 dbType.getLogicalType().putToDatabase(stmt, 1, dbType.getJdbcWriteType());
                 if (reversePolymorphicTypeFieldName != null)
                 {
                     stmt.setString(2, .getPolymorphicTypeMapper().convert(.getEntityType()));
                 }
                 final TypeInfo<K> primaryKeyType = Common.getPrimaryKeyType(provider.getTypeManager(), (Class<? extends RawEntity<K>>) remoteType);
                 final ResultSet res = stmt.executeQuery();
                 try
                 {
                     while (res.next())
                     {
                         EntityInfo entityInfo = .resolveEntityInfo((remotePolymorphicTypeFieldName == null ? remoteType : .getPolymorphicTypeMapper().invert(remoteTyperes.getString(remotePolymorphicTypeFieldName))));
                         if (selectFields.remove(.))
                         {
                             selectFields.addAll(entityInfo.getFieldNames());
                         }
                         final RawEntity returnValueEntity = .peer(entityInfoprimaryKeyType.getLogicalType().pullFromDatabase(resthroughTypereturnField));
                         final CacheLayer returnLayer = .getProxyForEntity(returnValueEntity).getCacheLayer(returnValueEntity);
                         returnLayer.put(remotePrimaryKeyFieldres.getObject(1));
                         for (final String field : selectFields)
                         {
                             returnLayer.put(fieldres.getObject(field));
                         }
                         back.add(returnValueEntity);
                     }
                 }
                 finally
                 {
                     res.close();
                 }
             }
             finally
             {
                 stmt.close();
             }
         }
         finally
         {
             conn.close();
         }
         return back.toArray((RawEntity[]) Array.newInstance(remoteTypeback.size()));
     }
 
     private RawEntity[] fetchOneToMany(final Method methodfinal OneToMany annotationthrows SQLExceptionNoSuchMethodException
     {
         final Class remoteType = method.getReturnType().getComponentType();
         final EntityInfo entityInfo = .resolveEntityInfo(remoteType);
         final String remotePrimaryKeyFieldName = Common.getPrimaryKeyField(remoteTypegetFieldNameConverter());
         final String whereClause = where(annotationgetFieldNameConverter());
         final Preload preloadAnnotation = (PreloadremoteType.getAnnotation(Preload.class);
         final Method remoteMethod = remoteType.getMethod(annotation.reverse());
         final String remotePolymorphicTypeFieldName = getPolymorphicTypeFieldName(remoteMethod);
         final StringBuilder sql = new StringBuilder("SELECT ");
         final Set<StringselectFields = new LinkedHashSet<String>();
         selectFields.add(remotePrimaryKeyFieldName);
         if (preloadAnnotation != null && !) {
             selectFields.addAll(preloadValue(preloadAnnotationgetFieldNameConverter()));
             if (selectFields.contains(.)) {
                 sql.append(.);
             } else {
                 for (final String field : selectFields) {
                     sql.append(.getProvider().processID(field)).append(',');
                 }
                 sql.setLength(sql.length() - 1);
             }
         } else {
             sql.append(.getProvider().processID(remotePrimaryKeyFieldName));
         }
         sql.append(" FROM ").append(.getProvider().withSchema(getTableNameConverter().getName(remoteType)));
         sql.append(" WHERE ").append(.getProvider().processID(getFieldNameConverter().getName(remoteMethod))).append(" = ?");
         if (!whereClause.trim().equals("")) {
             sql.append(" AND (").append(.getProvider().processWhereClause(whereClause)).append(")");
         }
         if (remotePolymorphicTypeFieldName != null) {
             sql.append(" AND ").append(.getProvider().processID(remotePolymorphicTypeFieldName)).append(" = ?");
         }
         final Connection conn = .getProvider().getConnection();
         try {
             final PreparedStatement stmt = .getProvider().preparedStatement(connsql);
             try
             {
                 final TypeInfo<K> dbType = getTypeManager().getType(getClass());
                 dbType.getLogicalType().putToDatabase(stmt, 1, dbType.getJdbcWriteType());
                 if (remotePolymorphicTypeFieldName != null) {
                     stmt.setString(2, .getPolymorphicTypeMapper().convert(entityInfo.getEntityType()));
                 }
                 final ResultSet res = stmt.executeQuery();
                 try {
                     final List<RawEntity<?>> result = new ArrayList<RawEntity<?>>();
                     while (res.next()) {
                         final Object returnValue = Common.getPrimaryKeyType(getTypeManager(), (ClassremoteType).getLogicalType().pullFromDatabase(res, (ClassremoteTyperemotePrimaryKeyFieldName);
                         final RawEntity<?> returnValueEntity = .peer(entityInforeturnValue);
                         final CacheLayer returnLayer = .getProxyForEntity(returnValueEntity).getCacheLayer(returnValueEntity);
                         if (selectFields.remove(.))
                         {
                             selectFields.addAll(entityInfo.getFieldNames());
                         }
                         for (final String field : selectFields) {
                             returnLayer.put(fieldres.getObject(field));
                         }
                         result.add(returnValueEntity);
                     }
                     return result.toArray((RawEntity<?>[]) Array.newInstance(remoteTyperesult.size()));
                 } finally {
                     res.close();
                 }
             } finally {
                 stmt.close();
             }
         } finally {
             conn.close();
         }
     }
 
     private String getPolymorphicTypeFieldName(final Method remoteMethod)
     {
         final Class<?> attributeType = getAttributeTypeFromMethod(remoteMethod);
         return attributeType != null && attributeType.isAssignableFrom(getType())
                 && attributeType.isAnnotationPresent(Polymorphic.class) ? getFieldNameConverter().getPolyTypeName(remoteMethod) : null;
     }
 
     private RawEntity fetchOneToOne(final Method methodfinal OneToOne annotationthrows SQLExceptionNoSuchMethodException
     {
         final Class remoteType = method.getReturnType();
         final EntityInfo entityInfo = .resolveEntityInfo(remoteType);
         final String remotePrimaryKeyFieldName = Common.getPrimaryKeyField(remoteTypegetFieldNameConverter());
         final String whereClause = Common.where(annotationgetFieldNameConverter());
         final Method remoteMethod = remoteType.getMethod(annotation.reverse());
         final String remotePolymorphicTypeFieldName = getPolymorphicTypeFieldName(remoteMethod);
         final Preload preloadAnnotation = (PreloadremoteType.getAnnotation(Preload.class);
         final StringBuilder sql = new StringBuilder("SELECT ");
         final Set<StringselectFields = new LinkedHashSet<String>();
         selectFields.add(remotePrimaryKeyFieldName);
         if (preloadAnnotation != null && !)
         {
             selectFields.addAll(preloadValue(preloadAnnotationgetFieldNameConverter()));
             if (selectFields.contains(.))
             {
                 sql.append(.);
             }
             else
             {
                 for (final String field : selectFields)
                 {
                     sql.append(.getProvider().processID(field)).append(',');
                 }
                 sql.setLength(sql.length() - 1);
             }
         }
         else
         {
             sql.append(.getProvider().processID(remotePrimaryKeyFieldName));
         }
         sql.append(" FROM ").append(.getProvider().withSchema(getTableNameConverter().getName(remoteType)));
         sql.append(" WHERE ").append(.getProvider().processID(getFieldNameConverter().getName(remoteMethod))).append(" = ?");
         if (whereClause.trim().length() != 0)
         {
             sql.append(" AND (").append(.getProvider().processWhereClause(whereClause)).append(")");
         }
         if (remotePolymorphicTypeFieldName != null)
         {
             sql.append(" AND ").append(.getProvider().processID(remotePolymorphicTypeFieldName)).append(" = ?");
         }
         final Connection conn = .getProvider().getConnection();
         try
         {
             final PreparedStatement stmt = .getProvider().preparedStatement(connsql);
             try
             {
                 final TypeInfo<K> dbType = getTypeManager().getType(getClass());
                 dbType.getLogicalType().putToDatabase(stmt, 1, dbType.getJdbcWriteType());
                 if (remotePolymorphicTypeFieldName != null)
                 {
                     stmt.setString(2, .getPolymorphicTypeMapper().convert(entityInfo.getEntityType()));
                 }
                 final ResultSet res = stmt.executeQuery();
                 try
                 {
                     if (res.next())
                     {
                         final RawEntity returnValueEntity = .peer(entityInfo, Common.getPrimaryKeyType(getTypeManager(), (Class<? extends RawEntity<K>>) remoteType).getLogicalType().pullFromDatabase(res, (Class<K>) remoteTyperemotePrimaryKeyFieldName));
                         if (selectFields.remove(.))
                         {
                             selectFields.addAll(entityInfo.getFieldNames());
                         }
                         final CacheLayer returnLayer = .getProxyForEntity(returnValueEntity).getCacheLayer(returnValueEntity);
                         for (final String field : selectFields)
                         {
                             returnLayer.put(fieldres.getObject(field));
                         }
                         return returnValueEntity;
                     }
                     else
                     {
                         return null;
                     }
                 }
                 finally
                 {
                     res.close();
                 }
             }
             finally
             {
                 stmt.close();
             }
         }
         finally
         {
             conn.close();
         }
     }

    

See also:
AO-325
 
     @Deprecated
     private RawEntity[] legacyFetchManyToMany(final RawEntity<K> proxyfinal Method methodfinal ManyToMany manyToManyAnnotationthrows SQLException
     {
         final Class<? extends RawEntity<?>> throughType = manyToManyAnnotation.value();
         final Class<? extends RawEntity<?>> type = (Class<? extends RawEntity<?>>) method.getReturnType().getComponentType();
         return retrieveRelations(proxynull,
                 Common.getMappingFields(getFieldNameConverter(),
                         throughTypetype), throughType, (Class<? extends RawEntity>) type,
                         Common.where(manyToManyAnnotationgetFieldNameConverter()),
                         Common.getPolymorphicFieldNames(getFieldNameConverter(), throughType.getEntityType()),
                         Common.getPolymorphicFieldNames(getFieldNameConverter(), throughTypetype));
     }

    

See also:
AO-325
 
     @Deprecated
     private RawEntity[] legacyFetchOneToMany(final RawEntity<K> proxyfinal Method methodfinal OneToMany oneToManyAnnotationthrows SQLException
     {
         final Class<? extends RawEntity<?>> type = (Class<? extends RawEntity<?>>) method.getReturnType().getComponentType();
         return retrieveRelations(proxynew String[0],
                 new String[] { Common.getPrimaryKeyField(typegetFieldNameConverter()) },
                 (Class<? extends RawEntity>) typewhere(oneToManyAnnotationgetFieldNameConverter()),
                 Common.getPolymorphicFieldNames(getFieldNameConverter(), type.getEntityType()));
     }

    

See also:
AO-325
 
     @Deprecated
     private RawEntity legacyFetchOneToOne(final RawEntity<K> proxyfinal Method methodfinal OneToOne oneToOneAnnotationthrows SQLException
     {
         Class<? extends RawEntity<?>> type = (Class<? extends RawEntity<?>>) method.getReturnType();
         final RawEntity[] back = retrieveRelations(proxynew String[0],
                 new String[] { Common.getPrimaryKeyField(typegetFieldNameConverter()) },
                 (Class<? extends RawEntity>) type, Common.where(oneToOneAnnotationgetFieldNameConverter()),
                 Common.getPolymorphicFieldNames(getFieldNameConverter(), type.getEntityType()));
         return back.length == 0 ? null : back[0];
     }
 
     {
         return .getNameConverters().getTableNameConverter();
     }
 
     public K getKey() {
 		return ;
 	}
 
 	@SuppressWarnings("unchecked")
 	public void save(RawEntity entitythrows SQLException {
 		CacheLayer cacheLayer = getCacheLayer(entity);
 		String[] dirtyFields = cacheLayer.getDirtyFields();
 		
 		if (dirtyFields.length == 0) {
 			return;
 		}
 
         String table = .getName();
         final DatabaseProvider provider = this..getProvider();
         final TypeManager typeManager = provider.getTypeManager();
         Connection conn = null;
         PreparedStatement stmt = null;
         try
         {
             conn = provider.getConnection();
 			StringBuilder sql = new StringBuilder("UPDATE " + provider.withSchema(table) + " SET ");
 
 			for (String field : dirtyFields) {
 				sql.append(provider.processID(field));
 
 				if (cacheLayer.contains(field)) {
 					sql.append(" = ?,");
 				} else {
 					sql.append(" = NULL,");
 				}
 			}
 			
 			if (sql.charAt(sql.length() - 1) == ',') {
 				sql.setLength(sql.length() - 1);
 			}
 
 			sql.append(" WHERE ").append(provider.processID(.getPrimaryKey().getName())).append(" = ?");
 
 			stmt = provider.preparedStatement(connsql);
 
 			int index = 1;
 			for (String field : dirtyFields) {
 				if (!cacheLayer.contains(field)) {
 					continue;
 				}
 				
 				Object value = cacheLayer.get(field);
 				events.add(new PropertyChangeEvent(entityfieldnullvalue));
 				
 				if (value == null) {
                     this..getProvider().putNull(stmtindex++);
 				} else {
 					Class javaType = value.getClass();
 
 					if (value instanceof RawEntity) {
 						javaType = ((RawEntityvalue).getEntityType();
 					}
 
 					TypeInfo dbType = typeManager.getType(javaType);
                     dbType.getLogicalType().validate(value);
                     dbType.getLogicalType().putToDatabase(this.stmtindex++, valuedbType.getJdbcWriteType());
 					
 					if (!dbType.getLogicalType().shouldCache(javaType)) {
 						cacheLayer.remove(field);
 					}
 				}
 			}
             pkType.getLogicalType().putToDatabase(this.stmtindexpkType.getJdbcWriteType());
 			cacheLayer.clearFlush();
 			stmt.executeUpdate();
 
 				for (PropertyChangeEvent evt : events) {
 				}
 			}
 			cacheLayer.clearDirty();
         }
         finally
         {
             closeQuietly(stmt);
             closeQuietly(conn);
         }
 	}
 
 		.add(listener);
 	}
 
 		.remove(listener);
 	}
 
 	public int hashCodeImpl() {
 		return (.hashCode() + .hashCode()) % (2 << 15);
 	}
 
 	public boolean equalsImpl(RawEntity<K> proxyObject obj) {
 		if (proxy == obj) {
 			return true;
 		}
 
 		if (obj instanceof RawEntity<?>) {
 			RawEntity<?> entity = (RawEntity<?>) obj;
 
             String ourTableName = getTableNameConverter().getName(proxy.getEntityType());
             String theirTableName = getTableNameConverter().getName(entity.getEntityType());
 
 			return Common.getPrimaryKeyValue(entity).equals() && theirTableName.equals(ourTableName);
 		}
 
 		return false;
 	}
 
 	public String toStringImpl() {
         return .getName() + " {" + .getPrimaryKey().getName() + " = " + .toString() + "}";
 	}
 
 	public boolean equals(Object obj) {
 		if (obj == this) {
 			return true;
 		}
 
 		if (obj instanceof EntityProxy<?, ?>) {
 			EntityProxy<?, ?> proxy = (EntityProxy<?, ?>) obj;
 
 			if (proxy.entityInfo.equals() && proxy.key.equals()) {
 				return true;
 			}
 		}
 
 		return false;
 	}
 
 	public int hashCode() {
 		return hashCodeImpl();
 	}
 
 		// not atomic, but throughput is more important in this case
 		if ( == null) {
 		}
 		
 		return ;
 	}
 
 	Class<T> getType() {
 	}
 
 	// any dirty fields are kept in the cache, since they have yet to be saved
 	void flushCache(RawEntity<?> entity) {
 		getCacheLayer(entity).clear();
 	}
 
     private ReadWriteLock getLock(String field) {
 		try {
 			if (.containsKey(field)) {
 				return .get(field);
 			}
 			
 			.put(fieldback);
 			
 			return back;
 		} finally {
 		}
 	}
 
     private <V> V invokeGetter(RawEntity<?> entityFieldInfo<V> fieldInfothrows Throwable {
         CacheLayer cacheLayer = getCacheLayer(entity);
 
         Class<V> type = fieldInfo.getJavaType();
         String name = fieldInfo.getName();
 
         boolean shouldCache = fieldInfo.isCacheable();
 
         getLock(name).writeLock().lock();
         try {
             if (!shouldCache && cacheLayer.dirtyContains(name)) {
                 return handleNullReturn(nulltype);
             } else if (shouldCache && cacheLayer.contains(name)) {
                 Object value = cacheLayer.get(name);
 
                 if (instanceOf(valuetype)) {
                     //noinspection unchecked
                     return handleNullReturn((V) valuetype);
                 } else if (isBigDecimal(valuetype)) { // Oracle for example returns BigDecimal when we expect doubles
                     //noinspection unchecked
                     return (V) handleBigDecimal(valuetype);
                 } else if (RawEntity.class.isAssignableFrom(type)) {
                     //noinspection unchecked
                     EntityInfo<? extends RawEntityObjectremoteEntityInfo = .resolveEntityInfo((Class<? extends RawEntity>) type);
                     if (instanceOf(valueremoteEntityInfo.getPrimaryKey().getJavaType())) {
                         value = .peer(remoteEntityInfovalue);
 
                         cacheLayer.put(namevalue);
                         //noinspection unchecked
                         return handleNullReturn((V) valuetype);
                     }
                 }
                 cacheLayer.remove(name); // invalid cached value
             }
 
             V back = pullFromDatabase(fieldInfo);
 
             if (shouldCache) {
                 cacheLayer.put(nameback);
             }
 
             return handleNullReturn(backtype);
         } finally {
             getLock(name).writeLock().unlock();
         }
     }
 
     private <V> V pullFromDatabase(FieldInfo<V> fieldInfothrows SQLException {
         Class<V> type = fieldInfo.getJavaType();
         String name = fieldInfo.getName();
         final DatabaseProvider provider = .getProvider();
         Connection conn = null;
         PreparedStatement stmt = null;
         ResultSet res = null;
         V back = null;
         try {
             conn = provider.getConnection();
             StringBuilder sql = new StringBuilder("SELECT ");
 
             sql.append(provider.processID(name));
             String polyName = fieldInfo.getPolymorphicName();
             if (polyName != null) {
                 sql.append(',').append(provider.processID(polyName));
             }
 
             sql.append(" FROM ").append(provider.withSchema(.getName())).append(" WHERE ");
             sql.append(provider.processID(.getPrimaryKey().getName())).append(" = ?");
 
             stmt = provider.preparedStatement(connsql);
             TypeInfo<K> pkType = .getPrimaryKey().getTypeInfo();
             pkType.getLogicalType().putToDatabase(stmt, 1, getKey(), pkType.getJdbcWriteType());
 
             res = stmt.executeQuery();
             if (res.next()) {
                 back = convertValue(resprovider.shorten(name), provider.shorten(polyName), type);
             }
         } finally {
             closeQuietly(resstmtconn);
         }
         return back;
     }
 
     private <V> V handleNullReturn(V backClass<V> type) {
         return back != null ? back : Defaults.defaultValue(type);
 	}
 
 	private void invokeSetter(T entityString nameObject valueString polyNamethrows Throwable {
 		CacheLayer cacheLayer = getCacheLayer(entity);
 		
 		getLock(name).writeLock().lock();
 		try {
 			if (value instanceof RawEntity<?>) {
 				cacheLayer.markToFlush(((RawEntity<?>) value).getEntityType());
 				cacheLayer.markToFlush(entity.getEntityType());
 			}
 
 			cacheLayer.markDirty(name);
 			cacheLayer.put(namevalue);
 	
 			if (polyName != null) {
 				String strValue = null;
 	
 				if (value != null) {
                     strValue = .getPolymorphicTypeMapper().convert(((RawEntity<?>) value).getEntityType());
 				}
 
 				cacheLayer.markDirty(polyName);
 				cacheLayer.put(polyNamestrValue);
 			}
 		} finally {
 		}
 	}

    

See also:
AO-325
 
     @Deprecated
     private <V extends RawEntity<K>> V[] retrieveRelations(RawEntity<K> entityString[] inMapFields,
 			String[] outMapFieldsClass<V> typeString whereString[] thisPolyNamesthrows SQLException {
 		return retrieveRelations(entityinMapFieldsoutMapFieldstypetypewherethisPolyNamesnull);
 	}

    

See also:
AO-325
 
     @Deprecated
     private <V extends RawEntity<K>> V[] retrieveRelations(final RawEntity<K> entity,
                                                            String[] inMapFields,
                                                            final String[] outMapFields,
                                                            final Class<? extends RawEntity<?>> type,
                                                            final Class<V> finalType,
                                                            final String where,
                                                            final String[] thisPolyNames,
                                                            final String[] thatPolyNamesthrows SQLException
     {
 		if (inMapFields == null || inMapFields.length == 0) {
             inMapFields = Common.getMappingFields(getFieldNameConverter(), type.getEntityType());
 		}
 		List<V> back = new ArrayList<V>();
 		List<StringresPolyNames = new ArrayList<String>(thatPolyNames == null ? 0 : thatPolyNames.length);
 
         String table = getTableNameConverter().getName(type);
 		boolean oneToMany = type.equals(finalType);
 		final Preload preloadAnnotation = finalType.getAnnotation(Preload.class);
 
         final DatabaseProvider provider = .getProvider();
         Connection conn = null;
         PreparedStatement stmt = null;
         ResultSet res = null;
 		try {
             conn = provider.getConnection();
 			StringBuilder sql = new StringBuilder();
 			String returnField;
 			String throughField;
 			int numParams = 0;
 			
 			Set<StringselectFields = new LinkedHashSet<String>();
 			
 			if (oneToMany && inMapFields.length == 1 && outMapFields.length == 1 
 					&& preloadAnnotation != null && !) {
 				sql.append("SELECT ");		// one-to-many preload
 				
 				selectFields.add(outMapFields[0]);
 				selectFields.addAll(preloadValue(preloadAnnotationgetFieldNameConverter()));
 				
 				if (selectFields.contains(.)) {
 				} else {
 					for (String field : selectFields) {
 						sql.append(provider.processID(field)).append(',');
 					}
 					sql.setLength(sql.length() - 1);
 				}
 				
 				sql.append(" FROM ").append(provider.withSchema(table));
 				
 				sql.append(" WHERE ").append(provider.processID(inMapFields[0])).append(" = ?");
 				
 				if (!where.trim().equals("")) {
                     sql.append(" AND (").append(.getProvider().processWhereClause(where)).append(")");
 				}
 				
 				if (thisPolyNames != null) {
 					for (String name : thisPolyNames) {
 						sql.append(" AND ").append(provider.processID(name)).append(" = ?");
 					}
 				}
 				
 				numParams++;
 				returnField = outMapFields[0];
 			}
             else if (!oneToMany && inMapFields.length == 1 && outMapFields.length == 1 && preloadAnnotation != null && !// many-to-many preload
             {
                 final String finalTable = getTableNameConverter().getName(finalType);
                 final String finalTableAlias = "f";
                 final String tableAlias = "t";
 
                 returnField = .getProvider().shorten(finalTable + "__aointernal__id");
                 throughField = .getProvider().shorten(table + "__aointernal__id");
 
 				sql.append("SELECT ");
 
                 String finalPKField = Common.getPrimaryKeyField(finalTypegetFieldNameConverter());
 
 				selectFields.add(finalPKField);
 				selectFields.addAll(preloadValue(preloadAnnotationgetFieldNameConverter()));
 
                 if (selectFields.contains(.))
                 {
                     selectFields.remove(.);
                     selectFields.addAll(Common.getValueFieldsNames(finalTypegetFieldNameConverter()));
                 }
 
                 sql.append(finalTableAlias).append('.').append(provider.processID(finalPKField));
                 sql.append(" AS ").append(provider.quote(returnField)).append(',');
 
                 selectFields.remove(finalPKField);
 
                 sql.append(tableAlias).append('.').append(provider.processID(Common.getPrimaryKeyField(typegetFieldNameConverter())));
 				sql.append(" AS ").append(provider.quote(throughField)).append(',');
 
 				for (String field : selectFields) {
 					sql.append(finalTableAlias).append('.').append(provider.processID(field)).append(',');
 				}
 				sql.setLength(sql.length() - 1);
 
 				if (thatPolyNames != null) {
 					for (String name : thatPolyNames) {
 						String toAppend = table + '.' + name;
 
 						resPolyNames.add(toAppend);
 						sql.append(',').append(provider.processID(toAppend));
 					}
 				}
 
 				sql.append(" FROM ").append(provider.withSchema(table)).append(" ").append(tableAlias).append(" INNER JOIN ");
 				sql.append(provider.withSchema(finalTable)).append(" ").append(finalTableAlias).append(" ON ");
 				sql.append(tableAlias).append('.').append(provider.processID(outMapFields[0]));
 				sql.append(" = ").append(finalTableAlias).append('.').append(provider.processID(finalPKField));
 
 				sql.append(" WHERE ").append(tableAlias).append('.').append(
 						provider.processID(inMapFields[0])).append(" = ?");
 
 				if (!where.trim().equals("")) {
                     sql.append(" AND (").append(.getProvider().processWhereClause(where)).append(")");
 				}
 
 				if (thisPolyNames != null) {
 					for (