package com.jqmobile.core.server.db.orm; import java.lang.reflect.Field; import java.sql.Connection; import java.sql.SQLException; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.UUID; import com.jqmobile.core.orm.DBColumn; import com.jqmobile.core.orm.DBTable; import com.jqmobile.core.orm.TableUtil; import com.jqmobile.core.orm.exception.ORMException; import com.jqmobile.core.orm.exception.ORMNotDBColumnException; import com.jqmobile.core.orm.exception.ORMNotDBTableException; import com.jqmobile.core.orm.exception.ORMTableParmaryRepeatException; import com.jqmobile.core.utils.TypeArgFinder; import com.jqmobile.core.utils.plain.BeanUtils; import com.jqmobile.core.utils.plain.StringUtils; public class BaseDBTable { private final Class<?> tableClass; private final DBTable dbLable; private BaseDBColumn parmaryId; private List<BaseDBColumn> mappingFields = new ArrayList<BaseDBColumn>(); private List<Class<?>> childClasses=new ArrayList<Class<?>>(); private boolean ifCreateTable=false;//是否已创建表 private boolean ifUpdateTable=false;//是否已更新表 private boolean ifCreateChildTable=false;//是否已创建中间表 private String createTableSql,insertSql,updateSql,dropTableSql,deleteSql,findSql; private final static Map<String, BaseDBTable> map = Collections.synchronizedMap(new HashMap<String, BaseDBTable>()); public static BaseDBTable getInstance(Class<?> c) throws ORMNotDBTableException { synchronized (map) { if(!map.containsKey(c.getName())){ map.put(c.getName(), new BaseDBTable(c)); } } return map.get(c.getName()); } public boolean hasChild(){ return BaseTableUtil.isObject(tableClass); } /** * 自动更新表 * @throws ORMException */ public void updateTable(Connection conn) throws ORMException{ if(!ifUpdateTable&&!tableClass.isAssignableFrom(ORMDBTable.class)){ TableUtil btu; btu = BaseTableUtil.getInstance(conn); btu.updateTable(tableClass); ifCreateTable=true; } } /** * 自动创建中间表 * @param c * @param childClass * @param conn * @throws ORMException */ public void autoCreateMiddleTable(Class<?> c, Class<?> childClass,Connection conn) throws ORMException{ if(!ifCreateChildTable){ TableUtil btu; btu = BaseTableUtil.getInstance(conn); btu.createMiddleTable(c, childClass); } } /** * 自动验证表 * * @throws ORMException * @throws SQLException */ private void autoValiTable(Connection conn) throws SQLException, ORMException { TableUtil tableUtil = TableUtilFactory.instance(conn); tableUtil.autoUpdateTable(tableClass); } public void autoCreateTable(Connection conn){ if(!ifCreateTable){ ifCreateTable=true; try { autoValiTable(conn); } catch (SQLException e) { e.printStackTrace(); } catch (ORMException e) { e.printStackTrace(); } } } private BaseDBTable(Class<?> c) throws ORMNotDBTableException{ this.tableClass = c; this.dbLable = c.getAnnotation(DBTable.class); if(null == dbLable){ throw new ORMNotDBTableException(); } initSql(); } public BaseDBColumn getParmaryId() { return parmaryId; } public DBTable getDBTable() { return dbLable; } public List<BaseDBColumn> getMappingFields() { return mappingFields; } public String getTableName(){ if(DBTable.DefaultValue.equals(dbLable.name())) return tableClass.getName().substring(tableClass.getName().lastIndexOf(".")+1); return dbLable.name(); } public Class<?> getTableClass() { return tableClass; } private void initSql(){ clear(); Field[] fields = BeanUtils.getAllFields_Cache(tableClass); StringBuilder creatTableSql=new StringBuilder("create table "), dropTableSql=new StringBuilder(" DROP TABLE "), insertDataSql=new StringBuilder("insert into "), iValues = new StringBuilder(" ( "), updateDataSql=new StringBuilder("update "), deleteDataSql=new StringBuilder(" delete from "), findDataSql=new StringBuilder(" select * from "); String tableName = getTableName(); creatTableSql.append(tableName); creatTableSql.append(" ( "); dropTableSql.append(tableName); insertDataSql.append(tableName); insertDataSql.append("("); updateDataSql.append(tableName); updateDataSql.append(" set \n"); deleteDataSql.append(tableName); deleteDataSql.append(" where "); findDataSql.append(tableName); findDataSql.append(" where "); boolean isFirst = true; //临时变量,用于储存主键列名 String tempId=""; for(Field f : fields){ //$开头的过滤掉 if(f.getName().contains("$")) continue; //集合过滤掉 if (Collection.class.isAssignableFrom(f.getType())) { childClasses.add(TypeArgFinder.getFieldClassGenricType(f)); continue; } if(Map.class.isAssignableFrom(f.getType())||Object[].class.isAssignableFrom(f.getType())) throw new ORMNotDBColumnException("暂时不支持此类型自动映射:【"+f.getName()+"】"+f.getType().getName());; //映射类过滤掉 if(!String.class.isAssignableFrom(f.getType())&&!UUID.class.isAssignableFrom(f.getType())&&!f.getType().isPrimitive()){ childClasses.add(f.getType()); continue; } BaseDBColumn column = BaseDBColumn.getInstance(f); //无映射的过滤掉 if(!column.isMapping()) continue; //paimary id if(column.isPaimaryId()){ //将主键列名赋值给临时变量 tempId=column.getColumnName(); if(null == parmaryId){ this.parmaryId = column; deleteDataSql.append(column.getColumnName()); deleteDataSql.append("=?"); findDataSql.append(column.getColumnName()); findDataSql.append("=?"); }else{ throw new ORMTableParmaryRepeatException(" old:"+parmaryId.getColumnName()+",now:"+f.getName()); } } String columnType = column.getColumnType(); String columnName = column.getColumnName(); if(!isFirst&&!"".equals(columnType)&&!"".equals(columnName)) creatTableSql.append(" , \n "); creatTableSql.append(" "); creatTableSql.append(columnName); creatTableSql.append(" "); creatTableSql.append(columnType); DBColumn dbColumn=column.getField().getAnnotation(DBColumn.class); if(dbColumn!=null&&!dbColumn.canNull()) creatTableSql.append(" NOT NULL"); if(!isFirst&&!"".equals(columnType)&&!"".equals(columnName)) insertDataSql.append(" , "); insertDataSql.append(columnName); if(!isFirst&&!"".equals(columnType)&&!"".equals(columnName)) iValues.append(" , "); if(!"".equals(columnType)&&!"".equals(columnName)) iValues.append(" ? "); updateDataSql.append(columnName); updateDataSql.append("=?, "); f.setAccessible(true); mappingFields.add(column); isFirst = false; } creatTableSql.append(" ,PRIMARY KEY ("+tempId+") \n)"); iValues.append(" ) "); insertDataSql.append(" ) "); insertDataSql.append(" values "); insertDataSql.append(iValues); String s = updateDataSql.toString(); if(s.contains("=?,")){ updateDataSql.delete(s.lastIndexOf(","), updateDataSql.length()); } updateDataSql.append(" where "+tempId+" = ?"); this.createTableSql = creatTableSql.toString(); this.insertSql = insertDataSql.toString(); this.updateSql = updateDataSql.toString(); this.dropTableSql = dropTableSql.toString(); this.deleteSql = deleteDataSql.toString(); this.findSql = findDataSql.toString(); } private void clear() { parmaryId = null; } public List<Class<?>> getChildClasses() { if(hasChild()){ return childClasses; } return childClasses; } public String getCreateTableSql(){ if(null == createTableSql) initSql(); return createTableSql; } public String getDropTableSql(){ if(null == dropTableSql) initSql(); return dropTableSql; } public String getInstnerSql(){ if(null == insertSql) initSql(); return insertSql; } public String getUpdateSqlByPID(){ if(null == updateSql) initSql(); return updateSql; } public String getDeleteSqlByPID(){ if(null == deleteSql) initSql(); return deleteSql; } public String getFindSqlByPID() { if(null == findSql) initSql(); return findSql; } public String getQuerySql(String where) { String head = "select * from "+getTableName(); if(StringUtils.isEmpty(where, true)){ return head; }else if(where.trim().toLowerCase().startsWith("select")){ return where; }else if(where.trim().toLowerCase().startsWith("where")){ return head+" "+where; }else{ return head+" where "+where; } } public String getQueryRowSql(String where) { String head = "select count("+parmaryId.getColumnName()+") from "+getTableName(); if(StringUtils.isEmpty(where, true)){ return head; }else if(where.trim().toLowerCase().startsWith("select")){ return where; }else if(where.trim().toLowerCase().startsWith("where")){ return head+" "+where; }else{ return head+" where "+where; } } public String getModifySql(String set) { String head = "update "+getTableName()+" "; if(StringUtils.isEmpty(set, true)){ return ""; }else if(set.trim().toLowerCase().startsWith("update")){ return set; }else if(set.trim().toLowerCase().startsWith("set")){ return head+set; }else{ return head+" set "+set; } } public String getDeleteSql(String where) { String head = "delete from "+getTableName(); if(StringUtils.isEmpty(where, true)){ return head; }else if(where.trim().toLowerCase().startsWith("select")){ return where; }else if(where.trim().toLowerCase().startsWith("where")){ return head+" "+where; }else{ return head+" where "+where; } } }