JFinal 源码导读第六天(2) Save,Update分析

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);
	}




你可能感兴趣的:(update,jFinal,save)