package org.jboss.ejb.plugins.cmp.jdbc;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.List;
import javax.ejb.EJBException;
import javax.ejb.NoSuchEntityException;
import org.jboss.ejb.EntityEnterpriseContext;
import org.jboss.ejb.plugins.cmp.jdbc.bridge.JDBCFieldBridge;
import org.jboss.ejb.plugins.cmp.jdbc.bridge.JDBCCMPFieldBridge;
import org.jboss.ejb.plugins.cmp.jdbc.bridge.JDBCEntityBridge;
import org.jboss.ejb.plugins.cmp.jdbc.metadata.JDBCFunctionMappingMetaData;
import org.jboss.logging.Logger;
import org.jboss.deployment.DeploymentException;
public final class JDBCLoadEntityCommand
{
private final JDBCStoreManager manager;
private final JDBCEntityBridge entity;
private final Logger log;
private final JDBCFunctionMappingMetaData rowLockingTemplate;
public JDBCLoadEntityCommand(JDBCStoreManager manager) throws DeploymentException
{
this.manager = manager;
entity = (JDBCEntityBridge) manager.getEntityBridge();
boolean rawLocking = entity.getMetaData().hasRowLocking();
rowLockingTemplate = rawLocking ? entity.getMetaData().getTypeMapping().getRowLockingTemplate() : null;
log = Logger.getLogger(
this.getClass().getName() +
"." +
manager.getMetaData().getName());
}
public boolean execute(EntityEnterpriseContext ctx, boolean failIfNotFound)
{
return execute(null, ctx, failIfNotFound);
}
public void execute(JDBCCMPFieldBridge requiredField, EntityEnterpriseContext ctx)
{
execute(requiredField, ctx, true);
}
private boolean execute(JDBCCMPFieldBridge requiredField,
EntityEnterpriseContext ctx,
boolean failIfNotFound)
{
Object id = ctx.getId();
entity.injectPrimaryKeyIntoInstance(ctx, id);
ReadAheadCache readAheadCache = manager.getReadAheadCache();
if(readAheadCache.load(ctx))
{
if(requiredField == null || (requiredField != null && requiredField.isLoaded(ctx)))
{
return true;
}
}
ReadAheadCache.EntityReadAheadInfo info = readAheadCache.getEntityReadAheadInfo(id);
JDBCEntityBridge.FieldIterator loadIter = entity.getLoadIterator(requiredField, info.getReadAhead(), ctx);
if(!loadIter.hasNext())
return true;
List loadKeys = info.getLoadKeys();
String sql = (rowLockingTemplate != null ? getRawLockingSQL(loadIter, loadKeys.size()) : getSQL(loadIter, loadKeys.size()));
Connection con = null;
PreparedStatement ps = null;
ResultSet rs = null;
try
{
if (log.isDebugEnabled())
{
log.debug("Executing SQL: " + sql);
}
con = entity.getDataSource().getConnection();
ps = con.prepareStatement(sql);
if (entity.getFetchSize() > 0)
{
ps.setFetchSize(entity.getFetchSize());
}
int paramIndex = 1;
for (int i = 0; i < loadKeys.size(); i++)
{
paramIndex = entity.setPrimaryKeyParameters(ps, paramIndex, loadKeys.get(i));
}
rs = ps.executeQuery();
boolean mainEntityLoaded = false;
Object[] ref = new Object[1];
while (rs.next())
{
int index = 1;
ref[0] = null;
Object pk = null;
if (loadKeys.size() > 1)
{
index = entity.loadPrimaryKeyResults(rs, index, ref);
pk = ref[0];
}
if (loadKeys.size() == 1 || pk.equals(id))
{
loadIter.reset();
while(loadIter.hasNext())
{
JDBCCMPFieldBridge field = loadIter.next();
index = field.loadInstanceResults(rs, index, ctx);
field.setClean(ctx);
}
mainEntityLoaded = true;
}
else
{
loadIter.reset();
while(loadIter.hasNext())
{
JDBCCMPFieldBridge field = loadIter.next();
ref[0] = null;
index = field.loadArgumentResults(rs, index, ref);
readAheadCache.addPreloadData(pk, field, ref[0]);
}
}
}
loadIter.removeAll();
if (!mainEntityLoaded)
{
if (failIfNotFound)
throw new NoSuchEntityException("Entity not found: primaryKey=" + ctx.getId());
else
return false;
}
else
return true;
}
catch (EJBException e)
{
throw e;
}
catch (Exception e)
{
throw new EJBException("Load failed", e);
}
finally
{
JDBCUtil.safeClose(rs);
JDBCUtil.safeClose(ps);
JDBCUtil.safeClose(con);
}
}
private String getSQL(JDBCEntityBridge.FieldIterator loadIter, int keyCount)
{
StringBuffer sql = new StringBuffer(250);
sql.append(SQLUtil.SELECT);
JDBCFieldBridge[] primaryKeyFields = entity.getPrimaryKeyFields();
if (keyCount > 1)
{
SQLUtil.getColumnNamesClause(primaryKeyFields, sql);
sql.append(SQLUtil.COMMA);
}
SQLUtil.getColumnNamesClause(loadIter, sql);
sql.append(SQLUtil.FROM)
.append(entity.getQualifiedTableName())
.append(SQLUtil.WHERE);
String pkWhere = SQLUtil.getWhereClause(primaryKeyFields, new StringBuffer(50)).toString();
sql.append('(').append(pkWhere).append(')');
for (int i = 1; i < keyCount; i++)
{
sql.append(SQLUtil.OR).append('(').append(pkWhere).append(')');
}
return sql.toString();
}
private String getRawLockingSQL(JDBCEntityBridge.FieldIterator loadIter, int keyCount)
{
StringBuffer columnNamesClause = new StringBuffer(250);
if (keyCount > 1)
{
SQLUtil.getColumnNamesClause(entity.getPrimaryKeyFields(), columnNamesClause);
columnNamesClause.append(SQLUtil.COMMA);
}
SQLUtil.getColumnNamesClause(loadIter, columnNamesClause);
String tableName = entity.getQualifiedTableName();
String whereClause = SQLUtil.
getWhereClause(entity.getPrimaryKeyFields(), new StringBuffer(50)).toString();
if (keyCount > 0)
{
StringBuffer sb = new StringBuffer((whereClause.length() + 6) * keyCount + 4);
for (int i = 0; i < keyCount; i++)
{
if (i > 0)
sb.append(SQLUtil.OR);
sb.append('(').append(whereClause).append(')');
}
whereClause = sb.toString();
}
String[] args = new String[]{
columnNamesClause.toString(),
tableName,
whereClause,
null };
return rowLockingTemplate.getFunctionSql(args, new StringBuffer(300)).toString();
}
}