依旧是项目内的需求: 基于mysql进行的操作,因为要作为通用产品模型,对接不同地市,就是没有确定的mapper可用。所以采用jdbc去封装。
场景一:
条件:已经根据IDEA的database插件,利用POJO生成对应的实体类。
需求:获取所有表内容 (select * ),list输出。
public static final String ENTRY_PATH = "com.ucap.exchange.dataexchange.entity"; public static List<ComplexResults> getData(Connection conn) { //获取实体类包路径 String packageName = ENTRY_PATH; // Set<String> classNames = getClassName(packageName, false); List<ComplexResults> resultList = new ArrayList(); for (String className : classNames) { String tableName = className.substring(className.lastIndexOf(".") + 1); String sql = "select * from " + tableName ; try { Class tableNameClass = Class.forName(className); List fserd = queryToObj(tableNameClass, conn, sql); for (Object obj : fserd) { ComplexResults complexResults = new ComplexResults(null, tableName, System.currentTimeMillis(), ExchangeConstants.INSERT, obj, null); resultList.add(complexResults); } } catch (Exception e) { e.printStackTrace(); } } return resultList; }
/** * @param <T> 封装对象的泛型 * @param clazz 实体类对象 * @param sql sql语句 * @return list */public static <T> List<T> queryToObj(Class<T> clazz, Connection conn, String sql) { try { // 1. 获取结果集 PreparedStatement ps = conn.prepareStatement(sql); ResultSet rs = ps.executeQuery(); // 2. 将查询的结果和字段名称获取 获取所有的字段 ResultSetMetaData metaData = rs.getMetaData(); // 用来保存对象的 ArrayList<T> cols = new ArrayList<>(); while (rs.next()) { // 创建对象 T obj = clazz.newInstance(); for (int i = 1; i <= metaData.getColumnCount(); i++) { // 通过反射获取对应的字段 Field filed = clazz.getDeclaredField(metaData.getColumnLabel(i).toLowerCase()); filed.setAccessible(true); Object value = rs.getObject(metaData.getColumnLabel(i)); filed.set(obj, value); } cols.add(obj); } return cols; } catch (Exception e) { e.printStackTrace(); } return null;}
/** * 获取某包下所有类 * * @param packageName 包名 * @param isRecursion 是否遍历子包 * @return 类的完整名称 */public static Set<String> getClassName(String packageName, boolean isRecursion) { Set<String> classNames = null; ClassLoader loader = Thread.currentThread().getContextClassLoader(); String packagePath = packageName.replace(".", "/"); URL url = loader.getResource(packagePath); if (url != null) { String protocol = url.getProtocol(); if (protocol.equals("file")) { classNames = getClassNameFromDir(url.getPath(), packageName, isRecursion); } else if (protocol.equals("jar")) { JarFile jarFile = null; try { jarFile = ((JarURLConnection) url.openConnection()).getJarFile(); } catch (Exception e) { e.printStackTrace(); } if (jarFile != null) { getClassNameFromJar(jarFile.entries(), packageName, isRecursion); } } } else { /*从所有的jar包中查找包名*/ classNames = getClassNameFromJars(((URLClassLoader) loader).getURLs(), packageName, isRecursion); } return classNames;}
ComplexResults 是我封装的一个结果集对象,显式写一个构造方法,new对象时,生成实例用的。
queryToObj 方法,根据sql查询结果集获取结果 getMetaData(),再通过反射获取对应的字段 key,利用sql结果集 Set.getObject(key),获取值,把结果进行封装返回。
getClassName 方法,根据包路径获取包下对应实体对象放入set集合。
场景二:优化版。(去掉了实体类的绑定)
条件:已有数据库连接,动态扫描表结构。无实体类。
需求:获取所有表内容 (select * ),list输出。
public static final String EXCLUDE_TABLE = "sys_datachange_log";
public static List<ComplexResults> getData(Connection conn) throws SQLException { DatabaseMetaData dbmd = conn.getMetaData(); // 获取所有表 //获取数据库实例 String catalog = conn.getCatalog(); List<String> stringList = new ArrayList<>(); //获取所有的表对象 ResultSet tableRet = dbmd.getTables(catalog, null, null, new String[]{"TABLE"}); while (tableRet.next()) { stringList.add(tableRet.getString("TABLE_NAME")); } List<ComplexResults> resultList = new ArrayList(); for (String m_TableName : stringList) { if (!EXCLUDE_TABLE.equals(m_TableName)) { String columnName; String columnType_Sql; String columnType_Java; //获取表内的列,属性等信息 ResultSet colRet = dbmd.getColumns(catalog, "%", m_TableName, "%"); Map sqlResultsMap = new HashMap(); while (colRet.next()) { columnName = colRet.getString("COLUMN_NAME"); columnType_Sql = colRet.getString("TYPE_NAME"); sqlResultsMap.put(columnName,columnType_Sql); } String sql = "select * from " + m_TableName; List<Entity> entityList = SqlExecutor.query(conn, sql, new EntityListHandler()); for (Entity entity : entityList) { ComplexResults complexResults = new ComplexResults(null, m_TableName, System.currentTimeMillis(), ExchangeConstants.INSERT, entity, sqlResultsMap); resultList.add(complexResults); } } } return resultList; }
EXCLUDE_TABLE 此表是一个日志表,不需要获取内容。合理的利用了java.sql包下的 一些方法。再写第二个实现的时候,我对结果集对象 ComplexResults类 进行了修正,以便后面的逻辑更加方便使用。
原文地址:https://www.cnblogs.com/justtodo/p/11990759.html
时间: 2024-08-19 20:41:29