package com.jqmobile.core.server.db.orm; import java.lang.reflect.Field; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.UUID; import com.jqmobile.core.orm.DBColumn; import com.jqmobile.core.orm.ORM; import com.jqmobile.core.orm.TableUtil; import com.jqmobile.core.orm.exception.ORMException; import com.jqmobile.core.orm.exception.ORMNotDBTableException; import com.jqmobile.core.utils.plain.BeanUtils; import com.jqmobile.core.utils.plain.GUIDUtils; import com.jqmobile.core.utils.plain.Log; class BaseTableUtil implements TableUtil { private Connection connection; private Object lock = new Object(); private BaseTableUtil() { } private Connection getConnection() { return connection; } private void setConnection(Connection connection) { try { L10010: if (null == this.connection || this.connection.isClosed()) { this.connection = connection; } else { synchronized (lock) { try { lock.wait(1000); } catch (InterruptedException e) { } } break L10010; } } catch (SQLException e) { Log.getLog(getClass()).e(e); } this.connection = connection; } public static TableUtil getInstance(Connection conn) { BaseTableUtil util = new BaseTableUtil(); util.setConnection(conn); return util; } @Override public void createTable(Class<?> c) throws ORMException { PreparedStatement ps = null; try { BaseDBTable param = BaseDBTable.getInstance(c); try { if(!BaseTableUtil.getInstance(getConnection()).valiTableExist(param.getTableName())){ ps = getConnection() .prepareStatement(param.getCreateTableSql()); ps.execute(); insertORMDBTable(param); } } catch (SQLException e) { throw new ORMException(e); } } finally { if (ps != null) { try { ps.close(); } catch (SQLException e) { e.printStackTrace(); } } } } public void createMiddleTable(Class<?> c, Class<?> childClass) throws ORMException { List<String> tableNames=getTableName(c, childClass); boolean isCreate=false; for(String tableName:tableNames){ if(valiTableExist(tableName)){ isCreate=true; } } if(!isCreate){ PreparedStatement ps=null; try { String sql = "create table "+tableNames.get(0)+" (C1 binary(16),C2 binary(16)"+")"; ps = getConnection().prepareStatement(sql); ps.execute(); } catch (SQLException e) { throw new ORMException(e); }finally { if(ps!=null){ try { ps.close(); } catch (SQLException e) { e.printStackTrace(); } } } } } /** * 获取自动生成列名 * @param c * @param childClass * @return * @throws ORMNotDBTableException */ public static List<String> getTableName(Class<?> c, Class<?> childClass) throws ORMNotDBTableException{ List<String> names=new ArrayList<String>(); String name=""; String mainTableName=BaseDBTable.getInstance(c).getTableName(); String otherTableName=BaseDBTable.getInstance(childClass).getTableName(); mainTableName=mainTableName.length()>6?mainTableName.substring(mainTableName.length()-6):mainTableName; otherTableName=otherTableName.length()>6?otherTableName.substring(otherTableName.length()-6):otherTableName; int size=mainTableName.length()+otherTableName.length(); for (int i = 0; i < 2; i++) { if(i==0){ name=mainTableName+size+"_"+otherTableName+size; }else{ name=otherTableName+size+"_"+mainTableName+size; } names.add(name); } return names; } /** * 判断此属性是否是想要映射的实体类 * @param f * @return */ public static boolean isMappingObject(Field f){ if(f.getAnnotation(DBColumn.class)==null){ return !f.getType().isAssignableFrom(UUID.class) && !f.getType().isAssignableFrom(String.class) && !f.getType().isPrimitive(); }else{ return f.getAnnotation(DBColumn.class).mapping()&&!f.getType().isAssignableFrom(UUID.class) && !f.getType().isAssignableFrom(String.class) && !f.getType().isPrimitive(); } } /** * 是否包含子查询对象 * * @param c * @return */ public static boolean isObject(Class<?> c) { Field[] fields = BeanUtils.getAllFields_Cache(c); for (Field f : fields) { if (isMappingObject(f)) { return true; } } return false; } private void insertORMDBTable(BaseDBTable t) throws ORMNotDBTableException, ORMException, SQLException { // 修改表记录 Connection conn=getConnection(); ORM<ORMDBTable> orm = ORMFactory.instance(conn, ORMDBTable.class); ORMDBTable sdt = new ORMDBTable(); sdt.setClassUrl(t.getTableClass().getName()); sdt.setName(t.getTableName()); sdt.setRecid(GUIDUtils.getUUIDByText(sdt.getName())); ORMDBTable sdt2 = orm.find(GUIDUtils.getUUIDByText(sdt.getName())); int oldVersion; if(sdt2==null){ oldVersion=1; sdt.setVersion(oldVersion); orm.insert(sdt); conn.commit(); }else{ oldVersion=sdt2.getVersion(); sdt.setVersion(oldVersion+1); orm.update(sdt); conn.commit(); } } @Override public void updateTable(Class<?> c) throws ORMException { BaseDBTable param = BaseDBTable.getInstance(c); // if not find table, create table. if (!valiTableExist(param.getTableName())) { createTable(c); } else { try { PreparedStatement pre = getConnection() .prepareStatement( "SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = ?"); List<String> oldColumn = new ArrayList<String>(); List<Field> newColumn = new ArrayList<Field>(); try { pre.setString(1, param.getTableName()); ResultSet rs = pre.executeQuery(); try { while (rs.next()) { oldColumn.add(rs.getString(1)); } } finally { rs.close(); } } finally { pre.close(); } Field[] fields = BeanUtils.getAllFields_Cache(c); // 20130705 List<Field> oldFields = new ArrayList<Field>(); // for (Field field : fields) { if (field.getName().contains("$")) continue; BaseDBColumn lable = BaseDBColumn.getInstance(field); if (!lable.isMapping())//未映射的跳过 continue; if(Collection.class.isAssignableFrom(field.getType()))//集合属性跳过 continue; if (!String.class.isAssignableFrom(field.getType())&&!UUID.class.isAssignableFrom(field.getType())&&!field.getType().isPrimitive()) { continue; } String columnName = lable.getColumnName(); if (!oldColumn.contains(columnName) && !oldColumn.contains(columnName.toUpperCase())) { newColumn.add(field); } // 20130705 else { oldFields.add(field); } // } if (!newColumn.isEmpty()) { // (加入字段) StringBuilder sql = new StringBuilder("ALTER TABLE ");// SaasDBTable // ADD // sex // BOOLEAN // ") sql.append(param.getTableName()); String columnName, columnType; for (int i = 0; i < newColumn.size(); i++) { sql.append(" ADD "); BaseDBColumn column = BaseDBColumn .getInstance(newColumn.get(i)); columnName = column.getColumnName(); columnType = column.getColumnType(); // sql.append(" "); sql.append(columnName); sql.append(" "); sql.append(columnType); if (i != newColumn.size() - 1) sql.append(", \n"); } Statement stat = getConnection().createStatement(); try { stat.execute(sql.toString()); } finally { stat.close(); } insertORMDBTable(param); } } catch (SQLException e) { throw new ORMException(e); } } } @Override public void autoUpdateAllTables() throws ORMException { ORM<ORMDBTable> orm = ORMFactory.instance(getConnection(), ORMDBTable.class); List<ORMDBTable> tables = orm.getAll(); Class<?> c; for (ORMDBTable t : tables) { try { c = Class.forName(t.getClassUrl(), true, Thread.currentThread() .getContextClassLoader()); } catch (ClassNotFoundException e) { Log.getLog(this).w(e); continue; } if (!valiTableExist(t.getName())) { createTable(c); } else if (BaseDBTable.getInstance(c).getDBTable().version() > t .getVersion()) { updateTable(c); } } } /** * 自动建表 */ @Override public void autoUpdateTable(Class<?> c) throws ORMException { BaseDBTable param = BaseDBTable.getInstance(c); // if not find table, create table. if (!valiTableExist(param.getTableName())) { createTable(c); return; } // if have new version, update table. if (param.getDBTable().version() > 0) { ORM<ORMDBTable> orm = ORMFactory.instance(getConnection(), ORMDBTable.class); ORMDBTable table = orm.find(GUIDUtils.getUUIDByText(param .getTableName())); if (null == table) { table = new ORMDBTable(c); orm.insert(table); updateTable(c); } else if (param.getDBTable().version() > table.getVersion()) { updateTable(c); } } } @Override public boolean valiTableExist(String tableName) throws ORMException { boolean isExist = false; try { PreparedStatement pre = getConnection().prepareStatement( "SHOW TABLES LIKE ?"); try { pre.setString(1, tableName); ResultSet rs = pre.executeQuery(); try { isExist = rs.next(); } finally { rs.close(); } } finally { pre.close(); } } catch (SQLException e) { throw new ORMException(e); } return isExist; } }