【问题标题】:java reflection for generic type when using jdbc使用jdbc时泛型类型的java反射
【发布时间】:2020-09-02 10:57:01
【问题描述】:

在 C# 中,我有一个实用程序可以将 Datatable 转换为指定模型的列表,如下所示:

Datatable dt = conn.GetDataTable(); 
List<BookModel> result = EntityHelper<BookModel>.GetListModel(dataTable); 

而使用泛型的GetListModel()方法是这样的:

public static List<T> GetListModel(DataTable dt)
    {
        List<T> lObject= new List<T>();
        for (int i = 0; i < dt.Rows.Count; i++)
        {
            T obj = new T();
            for (int j = 0; j < dt.Columns.Count; j++)
            {
                int index = IndexOfField( dt.Columns[j].ColumnName );
                if (index != -1)
                {
                    PropertyInfo pi = obj.GetType().GetProperties()[index];
                    Type propType = pi.PropertyType;
                    if (propType.IsGenericType && (propType.GetGenericTypeDefinition() == typeof( Nullable<> )))
                    {
                        propType = propType.GetGenericArguments()[0];
                    }
                    if (propType.IsEnum)
                    {
                        int objectValue = 0;
                        Int32.TryParse( dt.Rows[i][j].ToString(), out objectValue );
                        pi.SetValue( obj, Enum.ToObject( propType, objectValue ), null );
                    }
                    else if (dt.Columns[j].DataType == propType && dt.Rows[i][j] != DBNull.Value)
                    {
                        pi.SetValue( obj, dt.Rows[i][j], null );
                    }
                    else if ((propType.Name.Equals( "Boolean" ) || propType.Name.Equals( "bool" )) && dt.Rows[i][j] != DBNull.Value)
                    {
                        pi.SetValue( obj, Convert.ToBoolean( dt.Rows[i][j] ), null );
                    }
                }
            }

            lObject.Add( obj );
        }
        return lObject;
    }

这就是 C# 的故事,现在回到 Java。我正在使用 JDBC 执行存储过程并返回一个 ResultSet。但是我发现在 Java 中,泛型类型在运行时会删除它的信息,所以我不能这样做:

public static <T> List<T> castObject(ResultSet rs)
{
    T x = new T(); //IMPOSSIBLE ;___;
    Field[] fields = x.getClass().getDeclaredFields();
     for(Field field: fields) 
     { 
         field.setAccessible(true); 
     }
    ....
}

如果无法创建这样的实用程序,那么在获得 resulset 后是否可以减少样板代码?我的表有 30 列,我不想处理这样的代码:

actor.setFirstName(rs.getString("first_name"));
actor.setLastName(rs.getString("last_name"));
...

【问题讨论】:

  • “薪水和偏爱 Java 的公司数量可悲地高于 C#”。可悲?不要冒犯您寻求帮助的人:P
  • 但是……这与您的问题完全无关,而且会分散注意力。我把它编辑了。以便人们可以专注于您的实际问题

标签: java c# jdbc reflection resultset


【解决方案1】:

您可以通过将 Class 实例作为参数传递给您的方法来实例化该类。具体操作方式取决于您使用的 Java 版本,但这里是 Java 9 及更高版本的示例(尽管早期版本类似):

public static <T> List<T> castObject(ResultSet rs, Class<T> clazz) throws NoSuchMethodException,
        IllegalAccessException, InvocationTargetException, InstantiationException {

    Constructor<T> constructor = clazz.getConstructor();
    T t = constructor.newInstance();
    ...
}

调用方法:

List<BookModel> bookModels = castObject(rs, BookModel.class);

尽管调用 setAccessible 可能会有问题。此讨论显示了一种解决方法。 How to solve InaccessibleObjectException ("Unable to make {member} accessible: module {A} does not 'opens {package}' to {B}") on Java 9?

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-25
    相关资源
    最近更新 更多