package com.jqmobile.core.server.db.orm; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.math.BigDecimal; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Timestamp; import java.util.ArrayList; import java.util.Collection; import java.util.Date; import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.UUID; import com.jqmobile.core.orm.AutoVersionControl; 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.orm.exception.ORMParamNotRecognitionException; import com.jqmobile.core.orm.exception.VersionFieldTypeException; import com.jqmobile.core.utils.TypeArgFinder; import com.jqmobile.core.utils.plain.BeanUtils; import com.jqmobile.core.utils.plain.GUIDUtils; import com.jqmobile.core.utils.plain.Log; class ORMImpl2<T> extends ORMSImpl implements ORM<T> { private final BaseDBTable table; private final Class<T> beanClass; private final TableUtil btu; public ORMImpl2(Connection conn, Class<T> c) throws ORMNotDBTableException, ORMException { super(conn); beanClass = c; // 获取表对象 table = BaseDBTable.getInstance(c); // 自动验证表是否已创建,若未创建则创建,只运行一次 table.autoCreateTable(conn); // 自动验证表是否增加字段,只运行一次 table.updateTable(conn); // 初始化工具类对象 btu = TableUtilFactory.instance(conn); } /** * 根据传入对象获取主键id的二进制byte数组 * * @param obj * 主键属性对象 * @return */ private byte[] getPaimaryIdValue(Object obj) { if (obj instanceof UUID) { return GUIDUtils.getBytes((UUID) obj); } else if (obj instanceof byte[] || obj instanceof Byte[]) { return (byte[]) obj; } else if (obj instanceof String) { return GUIDUtils.getBytes(GUIDUtils.valueOf((String) obj)); } else { throw new ORMParamNotRecognitionException(obj); } } @Override public int insert(T t) throws ORMException { PreparedStatement ps = null; try { // 获取PreparedStatement ps = getPrepareStatement(table.getInstnerSql(), t); // 执行sql return ps.executeUpdate(); } catch (SQLException e) { // Log.getLog(getClass()).e(e); } catch (IllegalArgumentException e) { Log.getLog(getClass()).e(e); } catch (IllegalAccessException e) { Log.getLog(getClass()).e(e); } finally { if (ps != null) { try { ps.close(); } catch (SQLException e) { Log.getLog(getClass()).e(e); } } if (table.hasChild()) { // 获取关联类class List<Class<?>> childClasses = table.getChildClasses(); for (Class<?> childClass : childClasses) { // 判断是否进行级联操作 Field[] fields = BeanUtils.getAllFields_Cache(beanClass); for (Field f : fields) { f.setAccessible(true); BaseDBColumn column = BaseDBColumn.getInstance(f); if (column.isMapping() && (f.getType().isAssignableFrom(childClass) || (Collection.class.isAssignableFrom(f.getType()) && TypeArgFinder.getFieldClassGenricType(f) .isAssignableFrom(childClass)))) { if (column.isCascadeInsert()) { table.autoCreateMiddleTable(beanClass, childClass, getConnection()); // 从对象中获取所有关联对象 try { List<Object> objList = getChildObj(beanClass, childClass, t); // 循环插入数据 for (Object o : objList) { insertChildData(o, t); } } catch (IllegalArgumentException e) { Log.getLog(getClass()).e(e); } catch (IllegalAccessException e) { Log.getLog(getClass()).e(e); } } } } } } } return 0; } /** * 构建插入语句 * * @param obj * @param t * @return * @throws ORMException */ private String getInsertSql(Object obj, T t) throws ORMException { StringBuilder sb = new StringBuilder("insert into "); for (String tableName : BaseTableUtil.getTableName(t.getClass(), obj.getClass())) { if (btu.valiTableExist(tableName)) { sb.append(tableName + "(C1,C2"); } } sb.append(") values (?,?)"); return sb.toString(); } /** * 获取对象主键值byte类型 * * @param object * 包含主键的主对象 * @return * @throws IllegalArgumentException * @throws IllegalAccessException * @throws ORMNotDBTableException */ private byte[] getByteIdValue(Object object) throws IllegalArgumentException, IllegalAccessException, ORMNotDBTableException { BaseDBTable table = BaseDBTable.getInstance(object.getClass()); BaseDBColumn column = table.getParmaryId(); if (null != column) return getPaimaryIdValue(column.getField().get(object)); return null; } /** * 子表数据插入 * * @param obj * @param t * @throws ORMException * @throws IllegalAccessException * @throws IllegalArgumentException */ private void insertChildData(Object obj, T t) throws IllegalArgumentException, IllegalAccessException { // 判断是更新还是插入到子表 ORM orm; try { orm = ORMFactory.instance(getConnection(), obj.getClass()); orm.insert(obj); } catch (ORMException e) { try { orm = ORMFactory.instance(getConnection(), obj.getClass()); orm.update(obj); } catch (ORMException e1) { Log.getLog(getClass()).e(e); } } // 增加关系表中的数据 PreparedStatement ps = null; try { String sql = getInsertSql(obj, t); ps = getConnection().prepareStatement(sql); ps.setObject(1, getByteIdValue(t)); ps.setObject(2, getByteIdValue(obj)); ps.executeUpdate(); } catch (SQLException e) { Log.getLog(getClass()).e(e); } catch (ORMException e) { Log.getLog(getClass()).e(e); } finally { if (ps != null) { try { ps.close(); } catch (SQLException e) { Log.getLog(getClass()).e(e); } } } } /** * 获取子表对象 * * @param beanClass2 * @param childClass * @param t * @return * @throws IllegalAccessException * @throws IllegalArgumentException * @throws ORMException */ private List<Object> getChildObj(Class<T> beanClass2, Class<?> childClass, T t) throws ORMException, IllegalArgumentException, IllegalAccessException { Field[] fields = BeanUtils.getAllFields_Cache(beanClass2); List<Object> list = new ArrayList<Object>(); for (Field f : fields) { f.setAccessible(true); if (null != f.get(t)) { if (f.getType().isAssignableFrom(childClass)) { try { list.add(f.get(t)); break; } catch (IllegalArgumentException e) { Log.getLog(getClass()).e(e); } catch (IllegalAccessException e) { Log.getLog(getClass()).e(e); } } else if (List.class.isAssignableFrom(f.getType()) && getFieldClass(f).isAssignableFrom(childClass)) { list.addAll((List) f.get(t)); break; } else if (Set.class.isAssignableFrom(f.getType()) && getFieldClass(f).isAssignableFrom(childClass)) { list.addAll((Set) f.get(t)); break; } } } return list; } /** * 如果属性是普通类,则直接返回,如果是集合,则返回泛型 * * @param c * @return * @throws ORMException */ public static Class<?> getFieldClass(Field field) throws ORMException { if (List.class.isAssignableFrom(field.getType())) { return TypeArgFinder.getFieldClassGenricType(field); } else if (Set.class.isAssignableFrom(field.getType())) { return TypeArgFinder.getFieldClassGenricType(field); } else { return field.getType(); } } /** * ps获取 * * @param instnerSql * 初始化的插入语句 * @param t * 要插入的对象 * @return * @throws SQLException * @throws IllegalArgumentException * @throws IllegalAccessException */ private PreparedStatement getPrepareStatement(String instnerSql, T t) throws SQLException, IllegalArgumentException, IllegalAccessException { // 完整ps List<BaseDBColumn> columns = table.getMappingFields(); PreparedStatement ps = getPrepareStatement(instnerSql); for (int i = 0; i < columns.size(); i++) { BaseDBColumn column = columns.get(i); Object obj = column.getField().get(t); if (null == obj) { ps.setObject(i + 1, null); continue; } DBColumn dbColumn = column.getField().getAnnotation(DBColumn.class); // 主键赋值 if (column.isPaimaryId()) { ps.setObject(i + 1, getPaimaryIdValue(obj)); continue; } // 日期赋值 else if (dbColumn != null && dbColumn.date()) { long longDate = (Long) obj; Timestamp tsDate = new Timestamp(longDate == 0 ? new Date().getTime() : longDate); ps.setTimestamp(i + 1, tsDate); continue; } else if (dbColumn != null && dbColumn.id() == true) { ps.setObject(i + 1, getPaimaryIdValue(obj)); continue; } ps.setObject(i + 1, getParam(obj)); } return ps; } /** * 获取类中指定的版本字段 * * @param t * 实体对象 * @return */ private String getValidateWord(T t) { try { Method method = beanClass.getMethod("getVersionWord"); return (String) method.invoke(t); } catch (NoSuchMethodException e) { Log.getLog(getClass()).e(e); } catch (SecurityException e) { Log.getLog(getClass()).e(e); } catch (IllegalAccessException e) { Log.getLog(getClass()).e(e); } catch (IllegalArgumentException e) { Log.getLog(getClass()).e(e); } catch (InvocationTargetException e) { Log.getLog(getClass()).e(e); } return null; } /** * 获取实体对象中版本控制字段值 * * @param t * 实体对象 * @param validateWord * 指定版本字段名称 * @return */ private Object getEntityVW(T t, String validateWord) { try { Field field = beanClass.getDeclaredField(validateWord); if (field.getType() == long.class) { String entityVW = "get" + validateWord.substring(0, 1).toUpperCase() + validateWord.substring(1, validateWord.length()); Method method = beanClass.getMethod(entityVW); return (Object) method.invoke(t); } else { throw new VersionFieldTypeException("版本字段必修是long类型"); } } catch (NoSuchMethodException e) { Log.getLog(getClass()).e(e); } catch (SecurityException e) { Log.getLog(getClass()).e(e); } catch (IllegalAccessException e) { Log.getLog(getClass()).e(e); } catch (IllegalArgumentException e) { Log.getLog(getClass()).e(e); } catch (InvocationTargetException e) { Log.getLog(getClass()).e(e); } catch (NoSuchFieldException e) { Log.getLog(getClass()).e(e); } catch (VersionFieldTypeException e) { Log.getLog(getClass()).e(e); } return null; } private String getVerSql(T t) { // 获取类中指定的版本字段 String validateWord = getValidateWord(t); // 获取对象中版本值 Object entityVW = getEntityVW(t, validateWord); return " and " + validateWord + " = " + entityVW; } private boolean judgeInterface() { Class<?>[] classes = beanClass.getInterfaces(); for (Class<?> c : classes) { if (c.equals(AutoVersionControl.class)) { return true; } } return false; } @Override public int update(T t) throws ORMException { PreparedStatement ps = null; int row = 0; // 获取PreparedStatement try { StringBuilder sb = new StringBuilder(table.getUpdateSqlByPID()); if (judgeInterface()) { sb.append(getVerSql(t)); } ps = getPrepareStatement(sb.toString(), t); ps.setBytes(table.getMappingFields().size() + 1, getPaimaryIdValue(table.getParmaryId().getField().get(t))); row = ps.executeUpdate(); } catch (SQLException e) { Log.getLog(getClass()).e(e); } catch (IllegalArgumentException e) { Log.getLog(getClass()).e(e); } catch (IllegalAccessException e) { Log.getLog(getClass()).e(e); } finally { if (ps != null) { try { ps.close(); } catch (SQLException e) { Log.getLog(getClass()).e(e); } } if (row > 0) { if (table.hasChild()) { List<Class<?>> childClasses = table.getChildClasses(); for (Class<?> childClass : childClasses) { Field[] fields = BeanUtils.getAllFields_Cache(beanClass); for (Field f : fields) { f.setAccessible(true); BaseDBColumn column = BaseDBColumn.getInstance(f); if (column.isMapping() && (f.getType().isAssignableFrom(childClass) || (Collection.class.isAssignableFrom(f.getType()) && TypeArgFinder.getFieldClassGenricType(f).isAssignableFrom( childClass)))) { if (column.isCascadeUpdate()) { List<Object> objList; try { objList = getChildObj(beanClass, childClass, t); table.autoCreateMiddleTable(beanClass, childClass, getConnection()); deleteMiddleData(GUIDUtils.getGUID(getByteIdValue(t)), childClass); for (Object o : objList) { updateChildData(o, t); } } catch (IllegalArgumentException e) { Log.getLog(getClass()).e(e); } catch (IllegalAccessException e) { Log.getLog(getClass()).e(e); } catch (SQLException e) { Log.getLog(getClass()).e(e); } } } } } } } } return row; } /** * 更新映射表数据 * * @param obj * @param t * @throws IllegalAccessException * @throws IllegalArgumentException * @throws ORMException * @throws ORMNotDBTableException */ private void updateChildData(Object obj, T t) throws IllegalArgumentException, IllegalAccessException { insertChildData(obj, t); } @Override public int delete(String recid) throws ORMException { if ("".equals(recid)) return 0; return delete(UUID.fromString(recid)); } @Override public T find(String recid) { if ("".equals(recid)) return null; return find(UUID.fromString(recid)); } @Override public int delete(UUID recid) throws ORMException { PreparedStatement ps = null; try { ps = getPrepareStatement(table.getDeleteSqlByPID()); ps.setBytes(1, GUIDUtils.getBytes(recid)); return ps.executeUpdate(); } catch (SQLException e) { Log.getLog(getClass()).e(e); } finally { if (ps != null) { try { ps.close(); } catch (SQLException e) { Log.getLog(getClass()).e(e); } } if (table.hasChild()) { List<Class<?>> childClasses = table.getChildClasses(); for (Class<?> childClass : childClasses) { table.autoCreateMiddleTable(beanClass, childClass, getConnection()); try { Field[] fields = BeanUtils.getAllFields_Cache(beanClass); for (Field f : fields) { f.setAccessible(true); BaseDBColumn column = BaseDBColumn.getInstance(f); if (column.isMapping() && (f.getType().isAssignableFrom(childClass) || (Collection.class.isAssignableFrom(f.getType()) && TypeArgFinder.getFieldClassGenricType(f).isAssignableFrom( childClass)))) { if (column.isCascadeDelete()) { ORM orm = ORMFactory.instance(getConnection(), childClass); List<byte[]> ids = getMiddleTableIdsByMainObj(recid, childClass); for (byte[] id : ids) { orm.delete(GUIDUtils.getGUID(id)); } } } } deleteMiddleData(recid, childClass); } catch (SQLException e) { Log.getLog(getClass()).e(e); } } } } return 0; } /** * 主表删除(更新)数据,中间表对应关系删除 * * @param recid * 主表id * @param childClass * 字表类 * @throws SQLException * @throws ORMException */ private void deleteMiddleData(UUID recid, Class<?> childClass) throws SQLException, ORMException { for (String tableName : BaseTableUtil.getTableName(beanClass, childClass)) { if (btu.valiTableExist(tableName)) { String sql = "delete from " + tableName + " where C1=?"; PreparedStatement ps = getConnection().prepareStatement(sql); ps.setObject(1, GUIDUtils.getBytes(recid)); ps.executeUpdate(); } } } private List<byte[]> getMiddleTableIdsByMainObj(UUID recid, Class<?> childClass) throws ORMNotDBTableException, ORMException, SQLException { List<Object> list = new ArrayList<Object>(); List<byte[]> bytes = new ArrayList<byte[]>(); for (String tableName : BaseTableUtil.getTableName(beanClass, childClass)) { if (btu.valiTableExist(tableName)) { String query = "select C2 from " + tableName + " where C1=?"; PreparedStatement ps = getConnection().prepareStatement(query); ps.setBytes(1, GUIDUtils.getBytes(recid)); ResultSet rs = ps.executeQuery(); while (rs.next()) { bytes.add(rs.getBytes("C2")); } ORM orm = ORMFactory.instance(getConnection(), childClass); for (byte[] b : bytes) { Object obj = orm.find(GUIDUtils.getGUID(b)); if (null != obj) { list.add(obj); } } } } return bytes; } @Override public T find(UUID recid) { PreparedStatement ps = null; ResultSet rs = null; try { T t = beanClass.newInstance(); ps = getPrepareStatement(table.getFindSqlByPID()); ps.setBytes(1, GUIDUtils.getBytes(recid)); rs = ps.executeQuery(); while (rs.next()) { t = setObjValue(rs, t); if (table.hasChild()) { return fillChildObj(t, recid); } return t; } } catch (SQLException e) { Log.getLog(getClass()).e(e); } catch (InstantiationException e) { Log.getLog(getClass()).e(e); } catch (IllegalAccessException e) { Log.getLog(getClass()).e(e); } catch (IllegalArgumentException e) { Log.getLog(getClass()).e(e); } catch (ORMException e) { Log.getLog(getClass()).e(e); } finally { if (rs != null) { try { rs.close(); } catch (SQLException e) { Log.getLog(getClass()).e(e); } } if (ps != null) { try { ps.close(); } catch (SQLException e) { Log.getLog(getClass()).e(e); } } } return null; } /** * 非懒加载查询 * * @param t * @param recid * @return * @throws ORMException * @throws SQLException * @throws IllegalAccessException * @throws IllegalArgumentException */ private T fillChildObj(T t, UUID recid) throws ORMException, SQLException, IllegalArgumentException, IllegalAccessException { List<Class<?>> childClasses = table.getChildClasses(); List<byte[]> bytes = new ArrayList<byte[]>(); for (Class<?> childClass : childClasses) { Field[] fields = BeanUtils.getAllFields_Cache(beanClass); for (Field f : fields) { f.setAccessible(true); BaseDBColumn column = BaseDBColumn.getInstance(f); if (column.isMapping() && (f.getType().isAssignableFrom(childClass) || (Collection.class.isAssignableFrom(f.getType()) && TypeArgFinder.getFieldClassGenricType(f).isAssignableFrom(childClass)))) { if (column.isCascadeFind()) { List<Object> list = new ArrayList<Object>(); for (String tableName : BaseTableUtil.getTableName(beanClass, childClass)) { if (btu.valiTableExist(tableName)) { String query = "select C2 from " + tableName + " where C1=?"; PreparedStatement ps = getConnection().prepareStatement(query); ps.setBytes(1, GUIDUtils.getBytes(recid)); ResultSet rs = ps.executeQuery(); while (rs.next()) { bytes.add(rs.getBytes("C2")); } ORM orm = ORMFactory.instance(getConnection(), childClass); for (byte[] b : bytes) { Object obj = orm.find(GUIDUtils.getGUID(b)); if (null != obj) { list.add(obj); } } if (list.size() > 0) { t = setObjectValue(t, list); } bytes.clear(); } } } } } } return t; } /** * 查询通用方法 * * @param t * @param object * @throws IllegalAccessException * @throws IllegalArgumentException */ private T setObjectValue(T t, List<Object> list) throws IllegalArgumentException, IllegalAccessException { Field[] fields = BeanUtils.getAllFields_Cache(beanClass); Class<?> c = list.get(0).getClass(); for (Field f : fields) { f.setAccessible(true); BaseDBColumn column = BaseDBColumn.getInstance(f); if (column.isMapping() && f.getType().isAssignableFrom(c)) { f.set(t, list.get(0)); } else if (column.isMapping() && Collection.class.isAssignableFrom(f.getType()) && TypeArgFinder.getFieldClassGenricType(f).isAssignableFrom(c)) { if (List.class.isAssignableFrom(f.getType())) { f.set(t, list); } else if (Set.class.isAssignableFrom(f.getType())) { f.set(t, new HashSet(list)); } } } return t; } /** * rs封装成对象 * * @param rs * @param t * @return * @throws IllegalArgumentException * @throws IllegalAccessException * @throws SQLException * @throws ORMException */ private T setObjValue(ResultSet rs, T t) throws IllegalArgumentException, IllegalAccessException, SQLException, ORMException { List<BaseDBColumn> columns = table.getMappingFields(); for (BaseDBColumn column : columns) { DBColumn dbColumn = column.getField().getAnnotation(DBColumn.class); Field f = column.getField(); //如果是主键 if (column.isPaimaryId()) { byte[] id=rs.getBytes(column.getColumnName()); if(null!=id){ if (String.class.isAssignableFrom(f.getType())) { f.set(t, GUIDUtils.getGUID(id).toString()); continue; } else if (UUID.class.isAssignableFrom(f.getType())) { f.set(t, GUIDUtils.getGUID(id)); continue; } else if (byte[].class.isAssignableFrom(f.getType())) { f.set(t, id); continue; } else { throw new ORMException("主键只能是String或者UUID或者byte[]类型"); } }else{ continue; } } // 日期赋值 else if (dbColumn != null && dbColumn.date()) { long longDate = rs.getTimestamp(column.getColumnName()).getTime(); f.set(t, longDate); continue; } //如果是id标签 else if(String.class.isAssignableFrom(f.getType())&&dbColumn != null && dbColumn.id()){ byte[] id=rs.getBytes(column.getColumnName()); if(null!=id){ f.set(t, GUIDUtils.getGUID(rs.getBytes(column.getColumnName())).toString()); } continue; } //如果是double类型 else if(double.class.isAssignableFrom(f.getType())||Double.class.isAssignableFrom(f.getType())){ BigDecimal bd=rs.getBigDecimal(column.getColumnName()); if(bd!=null){ f.set(t, bd.doubleValue()); } continue; } f.set(t, rs.getObject(column.getColumnName())); } return t; } @Override public List<T> getAll() throws ORMException { return query(""); } @Override public List<T> query(String where, Object... args) throws ORMException { List<T> list = new ArrayList<T>(); PreparedStatement ps = null; ResultSet rs = null; try { ps = getPreparedStatement(table.getQuerySql(where), args); rs = ps.executeQuery(); while (rs.next()) { T t = beanClass.newInstance(); if (table.hasChild()) { list.add(fillChildObj(setObjValue(rs, t), GUIDUtils.getGUID((byte[]) rs.getObject(table.getParmaryId().getColumnName())))); } else { list.add(setObjValue(rs, t)); } } } catch (SQLException e) { Log.getLog(getClass()).e(e); } catch (InstantiationException e) { Log.getLog(getClass()).e(e); } catch (IllegalAccessException e) { Log.getLog(getClass()).e(e); } finally { if (rs != null) { try { rs.close(); } catch (SQLException e) { Log.getLog(getClass()).e(e); } } if (ps != null) { try { ps.close(); } catch (SQLException e) { Log.getLog(getClass()).e(e); } } } return list; } @Override public List<T> queryPage(String where, long startIndex, long endIndex, Object... args) throws ORMException { if ("".equals(where)) where = " 1=1"; where = where.replace(";", ""); return query(where + " limit " + startIndex + " ," + (endIndex - startIndex), args); } @Override public T queryFirst(String where, Object... args) throws ORMException { where = where.replace(";", ""); return query(where + " limit 1", args).size() > 0 ? query(where + " limit 1", args).get(0) : null; } @Override public int queryRow(String where, Object... args) throws ORMException { PreparedStatement ps = null; ResultSet rs = null; try { ps = getPreparedStatement(table.getQueryRowSql(where), args); rs = ps.executeQuery(); if (rs.next()) return rs.getInt(1); } catch (SQLException e) { Log.getLog(getClass()).e(e); } finally { if (rs != null) { try { rs.close(); } catch (SQLException e) { Log.getLog(getClass()).e(e); } } if (ps != null) { try { ps.close(); } catch (SQLException e) { Log.getLog(getClass()).e(e); } } } return 0; } @Override public int update(String set, Object... objs) throws ORMException { if ("".equals(set)) { return 0; } PreparedStatement ps = null; try { ps = getPreparedStatement(table.getModifySql(set), objs); return ps.executeUpdate(); } catch (SQLException e) { Log.getLog(getClass()).e(e); } finally { if (ps != null) { try { ps.close(); } catch (SQLException e) { Log.getLog(getClass()).e(e); } } } return 0; } @Override public int delete(String where, Object... args) throws ORMException { PreparedStatement ps = null; try { ps = getPreparedStatement(table.getDeleteSql(where), args); return ps.executeUpdate(); } catch (SQLException e) { Log.getLog(getClass()).e(e); } finally { if (ps != null) { try { ps.close(); } catch (SQLException e) { Log.getLog(getClass()).e(e); } } } return 0; } }