Java Generics, Reflection API & JDB C: невозможно сопоставить java .lang.Long и java. sql .Timestamp с типом - PullRequest
1 голос
/ 18 января 2020

Нужен метод для сопоставления вывода ResultSet с экземпляром LogEntity с использованием Generics и java .lang.reflect. *. Это проблема конструктора с типами полей Long & Timestamp.

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 Ответ

3 голосов
/ 18 января 2020
if (field.getType() == java.lang.Long.class) {
  // ...
  field.getType().getConstructor(java.lang.Long.class)
  // ...
}

Это попытка получить конструктор в классе Long, который принимает Long в качестве параметра.

Нет такого конструктора.

Возможно, вы имеете в виду getConstructor(long.class), который выберет этот конструктор ?

Выберите существующий конструктор. Или просто пропустите отражение:

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

(Вы можете сделать то же самое и для других ветвей. На самом деле нет необходимости вызывать конструкторы копирования ни для одного из них, поскольку вы уже можете получить экземпляры правильного типа из набор результатов).

...