项目实战,通过类对象,反射类属性等信息。通过数据库连接信息,获取所有的对象以及结果

Posted justtodo

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了项目实战,通过类对象,反射类属性等信息。通过数据库连接信息,获取所有的对象以及结果相关的知识,希望对你有一定的参考价值。

依旧是项目内的需求: 基于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类 进行了修正,以便后面的逻辑更加方便使用。
 

以上是关于项目实战,通过类对象,反射类属性等信息。通过数据库连接信息,获取所有的对象以及结果的主要内容,如果未能解决你的问题,请参考以下文章

Java—反射

反射常见方法

java反射机制

Java核心技术点之反射

Java---反射机制

Java关于反射