有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

Java泛型、反射API和JDBC:无法映射Java。朗和爪哇。sql。类型的时间戳

需要使用泛型和java将ResultSet的输出映射到LogEntity的实例的方法。朗朗。他们的问题是一些长期和;时间戳字段类型

JDK 1.8,Spring Boot 2.2.2,不,我不需要你的Hibernate或JDBCTemplate

LogEntity

package com.tb.register.core.entity;

import com.tb.register.core.annotation.ColumnName;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.sql.Timestamp;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class LogEntity {
  @ColumnName(name = "Rn")
  private Long rn;

  @ColumnName(name = "Id")
  private Long id;

  @ColumnName(name = "Name")
  private String name;

  @ColumnName(name = "Who_Made")
  private Long whoMade;

  @ColumnName(name = "When_Made")
  private Timestamp whenMade;

  @ColumnName(name = "Who_Made_Username")
  private String whoMadeUsername;
}

ColumnName注释:

package com.tb.register.core.annotation;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

@Retention(RetentionPolicy.RUNTIME)
public @interface ColumnName {
  String name();
}

现行方法:

public List<V> getData(
      Connection connection, GridEntity gridEntity, Class<? extends V> classObject) {
    PreparedStatement preparedStatement = null;
    ResultSet resultSet = null;
    List<V> rows = new ArrayList<>();
    try {
      preparedStatement = connection.prepareStatement(gridEntity.getMainSQL());
      GridEntity.bindObjectLimit(preparedStatement, gridEntity);
      resultSet = preparedStatement.executeQuery();
      resultSet.setFetchSize(300);
      Field[] fields = classObject.getDeclaredFields();
      for (Field field : fields) {
        field.setAccessible(true);
        log.info("{}, {}", field.getName(), field.getType());
      }
      while (resultSet.next()) {
        V row = classObject.getConstructor().newInstance();
        for (Field field : fields) {
          ColumnName columnName = field.getAnnotation(ColumnName.class);
          if (columnName != null) {
            try {
              if (field.getType() == java.lang.Long.class) {
                field.set(
                    row,
                    field
                        .getType()
                        .getConstructor(java.lang.Long.class)
                        .newInstance(resultSet.getLong(columnName.name())));
              } else if (field.getType() == java.sql.Timestamp.class) {
                field.set(
                    row,
                    field
                        .getType()
                        .getConstructor(java.sql.Timestamp.class)
                        .newInstance(resultSet.getTimestamp(columnName.name())));
              } else {
                field.set(
                    row,
                    field
                        .getType()
                        .getConstructor(String.class)
                        .newInstance(resultSet.getString(columnName.name())));
              }
            } catch (Exception e) {
              log.error("", e);
            }
          }
        }
        rows.add(row);
        //        list.add(
        //            new V(
        //                resultSet.getLong("Rn"),
        //                resultSet.getLong("Id"),
        //                resultSet.getString("Name"),
        //                resultSet.getLong("Who_Made"),
        //                resultSet.getDate("When_Made"),
        //                resultSet.getString("Who_Made_Username")));
      }
      return rows;
    } catch (Exception e) {
      log.error("", e);
    } finally {
      PoolManager.release(resultSet);
      PoolManager.release(preparedStatement);
    }
    return null;
  }

我们得到的是:

2020-01-18 21:33:47,754 INFO  [http-nio-9111-exec-2] com.tb.register.core.entity.GridEntity: 
where: [], 
mainSQL: select * from( select /*+ first_rows(10) */ t.*, row_number() over(order By t.id asc) Rn from fr_cc_logs_v t ) where rn between :lowerLimit And :upperLimit order by rn asc
countSQL: select count(*) from fr_cc_logs_v t
2020-01-18 21:33:47,765 INFO  [http-nio-9111-exec-2] com.tb.register.core.repository.GenericRepository: rn, class java.lang.Long
2020-01-18 21:33:47,767 INFO  [http-nio-9111-exec-2] com.tb.register.core.repository.GenericRepository: id, class java.lang.Long
2020-01-18 21:33:47,767 INFO  [http-nio-9111-exec-2] com.tb.register.core.repository.GenericRepository: name, class java.lang.String
2020-01-18 21:33:47,767 INFO  [http-nio-9111-exec-2] com.tb.register.core.repository.GenericRepository: whoMade, class java.lang.Long
2020-01-18 21:33:47,767 INFO  [http-nio-9111-exec-2] com.tb.register.core.repository.GenericRepository: whenMade, class java.sql.Timestamp
2020-01-18 21:33:47,769 INFO  [http-nio-9111-exec-2] com.tb.register.core.repository.GenericRepository: whoMadeUsername, class java.lang.String
2020-01-18 21:33:47,774 ERROR [http-nio-9111-exec-2] com.tb.register.core.repository.GenericRepository: 
java.lang.NoSuchMethodException: java.lang.Long.<init>(java.lang.Long)
    at java.lang.Class.getConstructor0(Class.java:3082)
    at java.lang.Class.getConstructor(Class.java:1825)
    at com.tb.register.core.repository.GenericRepository.getData(GenericRepository.java:63)
    at com.tb.register.core.repository.LogRepositoryImpl.getLogs(LogRepositoryImpl.java:74)
    at com.tb.register.core.repository.LogRepositoryImpl$$FastClassBySpringCGLIB$$b1dfd861.invoke(<generated>)

java.lang.NoSuchMethodException: java.sql.Timestamp.<init>(java.sql.Timestamp)
    at java.lang.Class.getConstructor0(Class.java:3082)
    at java.lang.Class.getConstructor(Class.java:1825)
    at com.tb.register.core.repository.GenericRepository.getData(GenericRepository.java:70)
    at com.tb.register.core.repository.LogRepositoryImpl.getLogs(LogRepositoryImpl.java:74)

共 (1) 个答案

  1. # 1 楼答案

    if (field.getType() == java.lang.Long.class) {
      // ...
      field.getType().getConstructor(java.lang.Long.class)
      // ...
    }
    

    这试图在Long类中获取一个构造函数,该类将Long作为参数

    没有这样的构造函数

    也许你的意思是getConstructor(long.class),哪个会选择this constructor

    选择一个已存在的构造函数。或者跳过反射:

    field.set(
        row,
        resultSet.getLong(columnName.name()));
    

    (您也可以对其他分支执行类似操作。事实上,这两个分支都不需要调用复制构造函数,因为您已经可以从结果集中获得正确类型的实例)