/** 解析SourceFloder下搜索到的文件名以config.xml结尾的文件,将其中配置的Bean返回 */ public List<Bean> getBeans() { List<String> fileList = Files.list(Files.root(), "^.*config.xml$", true); // 搜索以config.xml结尾的文件 log.info("Found " + fileList.size() + " Xml config files at " + Files.root()); List<Bean> beans = new ArrayList<Bean>(); for (String filePath : fileList) { NodeList beanNodes = (NodeList) Files.xpath(Files.build(filePath), "//bean", XPathConstants.NODESET); for (int length = (null == beanNodes ? -1 : beanNodes.getLength()), i = 0; i < length; i++) { Bean iocBean = new Bean(); // 一个新的Bean iocBean.name = Files.xpath(beanNodes.item(i), "@name", XPathConstants.STRING).toString(); String type = Files.xpath(beanNodes.item(i), "@class", XPathConstants.STRING).toString(); try { iocBean.type = Class.forName(type); } catch (ClassNotFoundException e) { // 配置文件中把类名写错了 throw new RuntimeException( "Class " + type + " not found , which is configured in " + filePath, e); } NodeList propertyNodes = (NodeList) Files.xpath(beanNodes.item(i), "property", XPathConstants.NODESET); for (int len = (null == propertyNodes ? -1 : propertyNodes.getLength()), m = 0; m < len; m++) { Field field = new Field(); // 一个新的Field field.name = (String) Files.xpath(propertyNodes.item(m), "@name", XPathConstants.STRING); field.type = Reflect.fieldType(iocBean.type, field.name); field.value = (String) Files.xpath(propertyNodes.item(m), "@value", XPathConstants.STRING); iocBean.fields.add(field); } beans.add(iocBean); log.debug("ADD BEAN: Xml " + iocBean.type.getName() + " " + iocBean.name); } } return beans; }
/** * Dao的辅助类,用以组装SQL * * @author li ([email protected]) * @version 0.1.8 (2012-05-08) */ public class QueryBuilder { private static final String MAP_ARG_SIGN = Files.load("config.properties").getProperty("dao.mapArgSign", "#"); /** 表示对象结构的beanMeta */ protected Bean beanMeta; /** 根据传入的ID,构建一个用于删除单条记录的SQL */ public String deleteById(Object id) { return "DELETE FROM " + beanMeta.table + " WHERE " + beanMeta.getId().column + "=" + wrap(id); } /** * 根据传入的SQL,构建一个用于删除若干条记录的SQL * * @param sql 传入的sql语句,可以包含'?'占位符和具名占位符 * @param args 替换sql中占位符的值,或者对应具名占位符的Map * @see li.dao.QueryBuilder#setArgs(String, Object[]) */ public String deleteBySql(String sql, Object[] args) { if (!Verify.startWith(sql, "DELETE")) { sql = "DELETE FROM " + beanMeta.table + " " + sql; } return setArgs(sql, args); // 处理args } /** 构造默认的COUNT(*)查询的SQL,查询表中的总记录数 */ public String countAll() { return "SELECT COUNT(*) FROM " + beanMeta.table; } /** * 根据传入的SQL,构造一个用于COUNT(*)查询的SQL * * @param sql 传入的sql语句,可以包含'?'占位符和具名占位符 * @param args 替换sql中占位符的值,或者对应具名占位符的Map * @see li.dao.QueryBuilder#setArgs(String, Object[]) */ public String countBySql(String sql, Object[] args) { if (!Verify.startWith(sql, "SELECT")) { // 不以SELECT开头 sql = "SELECT COUNT(*) FROM " + beanMeta.table + " " + sql; } else if (!Verify.regex(sql.toUpperCase(), "COUNT\\(.*\\)")) { // 不包括COUNT(*) sql = "SELECT COUNT(*) FROM " + sql.substring(sql.toUpperCase().indexOf("FROM") + 4, sql.length()).trim(); } int index = sql.toUpperCase().indexOf("LIMIT"); if (index > 0) { sql = sql.substring(0, index); // 去掉limit部分 } return setArgs(sql, args); // 处理args } /** 使用传入的ID,构造一个用于查询一条记录的SQL */ public String findById(Object id) { return "SELECT * FROM " + beanMeta.table + " WHERE " + beanMeta.getId().column + "=" + wrap(id); } /** 使用传入的SQL和参数,构造一个用于查询一条记录的SQL */ public String findBySql(String sql, Object[] args) { if (!Verify.startWith(sql, "SELECT")) { // 添加SELECT * FROM table 部分 sql = "SELECT * FROM " + beanMeta.table + " " + sql; } return setArgs(sql, args); // 先处理别名,再处理page } /** * 使用传入的page,构造一个用于分页查询的SQL * * @param page 分页对象 */ public String list(Page page) { return setPage("SELECT * FROM " + beanMeta.table, page); } /** * 根据传入的SQL和page,构造一个用于分页查询的SQL * * @param page 分页对象 * @param sql 传入的sql语句,可以包含'?'占位符和具名占位符 * @param args 替换sql中占位符的值,或者对应具名占位符的Map * @see li.dao.QueryBuilder#setPage(String, Page) * @see li.dao.QueryBuilder#setArgs(String, Object[]) */ public String listBySql(Page page, String sql, Object[] args) { if (!Verify.startWith(sql, "SELECT")) { // 添加SELECT * FROM table 部分 sql = "SELECT * FROM " + beanMeta.table + " " + sql; } return setPage(setArgs(sql, args), page); // 先处理别名,再处理args,最后处理page } /** 根据传入的对象构建一个用于更新一条记录的SQL */ public String update(Object entity) { String sql = "UPDATE " + beanMeta.table + " SET "; for (Field field : beanMeta.fields) { Object fieldValue = Reflect.get(entity, field.name); if (!beanMeta.getId().name.equals(field.name)) { // 更新所有属性,fieldValue可能为null sql += field.column + "=" + wrap(fieldValue) + ","; } } Object id = Reflect.get(entity, beanMeta.getId().name); return sql.substring(0, sql.length() - 1) + " WHERE " + beanMeta.getId().column + "=" + wrap(id); } /** 根据传入的对象构建一个用于更新一条记录的SQL,忽略对象中值为null的属性 */ public String updateIgnoreNull(Object entity) { String sql = "UPDATE " + beanMeta.table + " SET "; for (Field field : beanMeta.fields) { Object fieldValue = Reflect.get(entity, field.name); if (!beanMeta.getId().name.equals(field.name) && !Verify.isEmpty(fieldValue)) { // 更新所有属性,fieldValue可能为null sql += field.column + "=" + wrap(fieldValue) + ","; } } Object id = Reflect.get(entity, beanMeta.getId().name); return sql.substring(0, sql.length() - 1) + " WHERE " + beanMeta.getId().column + "=" + wrap(id); } /** * 根据传入的SQL,构建一个用于更新若干条记录的SQL * * @param sql 传入的sql语句,可以包含'?'占位符和具名占位符 * @param args 替换sql中占位符的值,或者对应具名占位符的Map * @see li.dao.QueryBuilder#setArgs(String, Object[]) */ public String updateBySql(String sql, Object[] args) { if (!Verify.startWith(sql, "UPDATE")) { sql = "UPDATE " + beanMeta.table + " " + sql; } return setArgs(sql, args); // 处理args } /** 根据传入的对象构建一个插入一条记录的SQL */ public String insert(Object entity) { String columns = " (", values = " VALUES ("; for (Field field : beanMeta.fields) { Object fieldValue = Reflect.get(entity, field.name); columns += field.column + ","; values += wrap(fieldValue) + ","; } columns = columns.substring(0, columns.length() - 1) + ")"; values = values.substring(0, values.length() - 1) + ")"; return "INSERT INTO " + beanMeta.table + columns + values; } /** 根据传入的对象构建一个插入一条记录的SQL,忽略为空的属性 */ public String insertIgnoreNull(Object entity) { String columns = " (", values = " VALUES ("; for (Field field : beanMeta.fields) { Object fieldValue = Reflect.get(entity, field.name); if (!Verify.isEmpty(fieldValue)) { // 略过为null的属性 columns += field.column + ","; values += wrap(fieldValue) + ","; } } columns = columns.substring(0, columns.length() - 1) + ")"; values = values.substring(0, values.length() - 1) + ")"; return "INSERT INTO " + beanMeta.table + columns + values; } /** * 如果args不为空的话,SQL会用args逐次替换SQL中的占位符 * * @param sql 传入的sql语句,可以包含'?'占位符或者具名参数占位符 * @param args 替换sql中 '?' 或具名参数占位符的值 * @see li.dao.QueryBuilder#setArgMap(String, Map) */ public String setArgs(String sql, Object[] args) { if (null != sql && sql.length() > 0 && null != args && args.length > 0) { // 非空判断 for (int i = 0; i < args.length; i++) { if (args[i] instanceof Map<?, ?>) { sql = setArgMap(sql, (Map<?, ?>) args[i]); // 替换具名参数 } else { sql = sql.replaceFirst("[?]", wrap(args[i])); // 为参数加上引号后替换问号 } } } return sql; } /** * 用Map中的值替换SQL中的具名参数 * * @param sql 传入的sql语句,可以包含#key占位符 * @param argMap 替换sql中#key 的键值Map */ public String setArgMap(String sql, Map<?, ?> argMap) { if (null != sql && sql.length() > 0 && null != argMap && argMap.size() > 0) { // 非空判断 for (Entry<?, ?> arg : argMap.entrySet()) { sql = sql.replaceAll(MAP_ARG_SIGN + arg.getKey(), wrap(arg.getValue())); // 为参数加上引号后替换问号 } } return sql; } /** 处理SQL参数 */ public String wrap(Object arg) { if (null == arg) { return "NULL"; } else if (arg instanceof Number || arg instanceof Boolean) { return arg + ""; // 数字和Boolean不加引号 } else if (arg instanceof java.util.Date) { // 日期 return "'" + Convert.format((java.util.Date) arg) + "'"; } else { return "'" + arg + "'"; // 其他类型 } } /** 为SQL添加分页语句 */ public String setPage(String sql, Page page) { if (!Verify.contain(sql, "LIMIT") && null != page) { // 分页 return sql + " LIMIT " + page.getFrom() + "," + page.getPageSize(); } return sql; } }