1.接上面源码getModel(Blog.class),下面就是代码的调用过程
/**
* Get model from http request.
*/
public <T> T getModel(Class<T> modelClass) {
return (T)ModelInjector.inject(modelClass, request, false);
}
public static <T> T inject(Class<?> modelClass, HttpServletRequest request, boolean skipConvertError) {
String modelName = modelClass.getSimpleName();
return inject(modelClass, StringKit.firstCharToLowerCase(modelName), request, skipConvertError);
}
@SuppressWarnings({ "rawtypes", "unchecked" })
public static final <T> T inject(Class<?> modelClass, String modelName, HttpServletRequest request, boolean skipConvertError) {
Object model = null;
try {
model = modelClass.newInstance();
} catch (Exception e) {
throw new ModelInjectException(e);
}
if (model instanceof Model)
injectActiveRecordModel((Model)model, modelName, request, skipConvertError);
else
injectCommonModel(model, modelName, request, modelClass, skipConvertError);
return (T)model;
}
@SuppressWarnings("rawtypes")
private static final void injectActiveRecordModel(Model<?> model, String modelName, HttpServletRequest request, boolean skipConvertError) {
TableInfo tableInfo = TableInfoMapping.me().getTableInfo(model.getClass());
String modelNameAndDot = modelName + ".";
Map<String, String[]> parasMap = request.getParameterMap();
for (Entry<String, String[]> e : parasMap.entrySet()) {
String paraKey = e.getKey();
if (paraKey.startsWith(modelNameAndDot)) {
String paraName = paraKey.substring(modelNameAndDot.length());
Class colType = tableInfo.getColType(paraName);
if (colType == null)
throw new ActiveRecordException("The model attribute " + paraKey + " is not exists.");
String[] paraValue = e.getValue();
try {
// Object value = Converter.convert(colType, paraValue != null ? paraValue[0] : null);
Object value = paraValue[0] != null ? TypeConverter.convert(colType, paraValue[0]) : null;
model.set(paraName, value);
} catch (Exception ex) {
if (skipConvertError == false)
throw new ModelInjectException("Can not convert parameter: " + modelNameAndDot + paraName, ex);
}
}
}
}
}
2.上面代码的核心就是将 表单的数据放入到该Map中
private Map<String, Object> attrs = DbKit.containerFactory.getAttrsMap(); // new HashMap<String, Object>();
3.下面两段代码我稍微解释一下例如:blog.title,就是将paraName=title,colType,就是获取到字段的类型(它是根据数据库的类型来判断的)tableInfo初始化的时候会将数据库表的类型放入到其中,前面的博客有介绍
String paraName = paraKey.substring(modelNameAndDot.length());
Class colType = tableInfo.getColType(paraName);
4.下面开始save方法
/**
* Save model.
*/
public boolean save() {
TableInfo tableInfo = tableInfoMapping.getTableInfo(getClass());
StringBuilder sql = new StringBuilder();
List<Object> paras = new ArrayList<Object>();
DbKit.dialect.forModelSave(tableInfo, attrs, sql, paras);
// if (paras.size() == 0) return false; // The sql "insert into tableName() values()" works fine, so delete this line
// --------
Connection conn = null;
PreparedStatement pst = null;
int result = 0;
try {
conn = DbKit.getConnection();
if (DbKit.dialect.isOracle())
pst = conn.prepareStatement(sql.toString(), new String[]{tableInfo.getPrimaryKey()});
else
pst = conn.prepareStatement(sql.toString(), Statement.RETURN_GENERATED_KEYS);
DbKit.dialect.fillStatement(pst, paras);
// for (int i=0, size=paras.size(); i<size; i++) {
// pst.setObject(i + 1, paras.get(i));
// }
result = pst.executeUpdate();
// if (isSupportAutoIncrementKey)
getGeneratedKey(pst, tableInfo); // getGeneratedKey(pst, tableInfo.getPrimaryKey());
getModifyFlag().clear();
return result >= 1;
} catch (Exception e) {
throw new ActiveRecordException(e);
} finally {
DbKit.close(pst, conn);
}
}
5.DbKit.dialect.forModelSave(tableInfo, attrs, sql, paras);下面语句就是拼装sql语句
public void forModelSave(TableInfo tableInfo, Map<String, Object> attrs, StringBuilder sql, List<Object> paras) {
sql.append("insert into `").append(tableInfo.getTableName()).append("`(");
StringBuilder temp = new StringBuilder(") values(");
for (Entry<String, Object> e: attrs.entrySet()) {
String colName = e.getKey();
if (tableInfo.hasColumnLabel(colName)) {
if (paras.size() > 0) {
sql.append(", ");
temp.append(", ");
}
sql.append("`").append(colName).append("`");
temp.append("?");
paras.add(e.getValue());
}
}
sql.append(temp.toString()).append(")");
}
5.上面的一些语句我好好解释一下
pst = conn.prepareStatement(sql.toString(), Statement.RETURN_GENERATED_KEYS);
6. ** Statement.RETURN_GENERATED_KEYS 获取mysql自动增长的值
**7.if (DbKit.dialect.isOracle())
pst = conn.prepareStatement(sql.toString(), new String[]{tableInfo.getPrimaryKey()});
这行代码表面该数据库使用的oracle,可以使用触发器来,下面这篇博客有介绍
http://my.oschina.net/calfer/blog/73490
8.getGeneratedKey(pst, tableInfo); 这段代码是获取主键的值
9.下面介绍一下update的逻辑
/**
* Update model.
*/
public boolean update() {
if (getModifyFlag().isEmpty())
return false;
TableInfo tableInfo = tableInfoMapping.getTableInfo(getClass());
String pKey = tableInfo.getPrimaryKey();
Object id = attrs.get(pKey);
if (id == null)
throw new ActiveRecordException("You can't update model without Primary Key.");
StringBuilder sql = new StringBuilder();
List<Object> paras = new ArrayList<Object>();
DbKit.dialect.forModelUpdate(tableInfo, attrs, getModifyFlag(), pKey, id, sql, paras);
if (paras.size() <= 1) { // Needn't update
return false;
}
// --------
Connection conn = null;
try {
conn = DbKit.getConnection();
int result = Db.update(conn, sql.toString(), paras.toArray());
if (result >= 1) {
getModifyFlag().clear();
return true;
}
return false;
} catch (Exception e) {
throw new ActiveRecordException(e);
} finally {
DbKit.close(conn);
}
}
10.DbKit.dialect.forModelUpdate(tableInfo, attrs, getModifyFlag(), pKey, id, sql, paras);
这句代码我介绍一下,就是通过getModifyFlag()相关方法来拼接sql
public void forModelUpdate(TableInfo tableInfo, Map<String, Object> attrs, Set<String> modifyFlag, String primaryKey, Object id, StringBuilder sql, List<Object> paras) {
sql.append("update `").append(tableInfo.getTableName()).append("` set ");
for (Entry<String, Object> e : attrs.entrySet()) {
String colName = e.getKey();
if (!primaryKey.equalsIgnoreCase(colName) && modifyFlag.contains(colName) && tableInfo.hasColumnLabel(colName)) {
if (paras.size() > 0)
sql.append(", ");
sql.append("`").append(colName).append("` = ? ");
paras.add(e.getValue());
}
}
sql.append(" where `").append(primaryKey).append("` = ?"); // .append(" limit 1");
paras.add(id);
}