package com.ctrip.platform.dal.dao.helper;
import java.lang.reflect.Field;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.util.Map;
import oracle.sql.TIMESTAMP;
import com.ctrip.platform.dal.dao.DalRowMapper;
import com.ctrip.platform.dal.dao.UpdatableEntity;
import com.ctrip.platform.dal.exceptions.DalException;
import com.ctrip.platform.dal.exceptions.ErrorCode;
public class DalDefaultJpaMapper<T> implements DalRowMapper<T>, SupportPartialResultMapping<T> {
private Class<T> clazz = null;
private String[] columnNames = null;
private Map<String, Field> fieldsMap = null;
private boolean ignorMissingFields = false;
public DalDefaultJpaMapper(Class<T> clazz) throws SQLException {
this.clazz = clazz;
EntityManager manager = EntityManager.getEntityManager(clazz);
this.columnNames = manager.getColumnNames();
this.fieldsMap = manager.getFieldMap();
}
@Override
public T map(ResultSet rs, int rowNum) throws SQLException {
try {
T instance = this.clazz.newInstance();
for (int i = 0; i < columnNames.length; i++) {
Field field = fieldsMap.get(columnNames[i]);
if(field == null)
if(ignorMissingFields)
continue;
else
throw new DalException(ErrorCode.FieldNotExists, clazz.getName(), columnNames[i]);
setValue(field, instance, rs, i);
}
if(instance instanceof UpdatableEntity)
((UpdatableEntity)instance).reset();
return instance;
} catch (Throwable e) {
throw DalException.wrap(e);
}
}
private void setValue(Field field, Object entity, ResultSet rs, int index)
throws ReflectiveOperationException, SQLException {
Object val = rs.getObject(columnNames[index]);
if (val == null) {
field.set(entity, val);
return;
}
// The following order is optimized for most cases
if (field.getType().equals(Long.class) || field.getType().equals(long.class)) {
field.set(entity, ((Number) val).longValue());
return;
}
if (field.getType().equals(Integer.class) || field.getType().equals(int.class)) {
field.set(entity, ((Number) val).intValue());
return;
}
if (field.getType().equals(Double.class) || field.getType().equals(double.class)) {
field.set(entity, ((Number) val).doubleValue());
return;
}
if (field.getType().equals(Float.class) || field.getType().equals(float.class)) {
field.set(entity, ((Number) val).floatValue());
return;
}
if (field.getType().equals(Byte.class) || field.getType().equals(byte.class)) {
field.set(entity, ((Number) val).byteValue());
return;
}
if (field.getType().equals(Short.class) || field.getType().equals(short.class)) {
field.set(entity, ((Number) val).shortValue());
return;
}
/**
* This is because oracle returns its own Timestamp type instead of standard java.sql.Timestamp
*/
if (field.getType().equals(Timestamp.class) && !(val instanceof Timestamp)) {
field.set(entity, rs.getTimestamp(columnNames[index]));
return;
}
field.set(entity, val);
}
@Override
public DalRowMapper<T> mapWith(String[] selectedColumns, boolean ignorMissingFields)
throws SQLException {
return new DalDefaultJpaMapper<T>(this, selectedColumns, ignorMissingFields);
}
/**
* For map partial result set with given column names.
* Copy fields from rawMapper
*
* @param rawMapper
* @param clazz
* @throws SQLException
*/
private DalDefaultJpaMapper(DalDefaultJpaMapper<T> rawMapper, String[] columnNames, boolean ignorMissingFields) throws SQLException {
this.clazz = rawMapper.clazz;
this.columnNames = columnNames;
this.fieldsMap = rawMapper.fieldsMap;
this.ignorMissingFields = ignorMissingFields;
}
}