Is there a way to make a Java method that maps an SQL result list to an entity class generic?

huangapple go评论57阅读模式
英文:

Is there a way to make a Java method that maps an SQL result list to an entity class generic?

问题

以下是翻译好的部分:

我有这个成功执行本地 SQL 查询的方法。没有问题。它将查询的结果列表映射到相关的实体类:

@Data
public class DemoManager {

  Transaction transaction;
  static Session session;
  Query query;
  DemoEntity demoResultList;


  String url = "...";
  String username = "...";
  String password = "...";
  Class<DemoEntity> demoEntity = DemoEntity.class;


  public void executiveQuery(String sql) {
    session = Base.getSessionFactory(url, username, password, demoEntity).openSession();
    transaction = session.beginTransaction();
    query = session.createNativeQuery(sql, demoEntity);
    demoResultList = (DemoEntity) query.getResultList().get(0);
    session.close();
  }

现在的问题是,我想将 `executiveQuery()` 方法变成通用的,这样当它被调用时,可以传递任何实体类作为参数,而不是每次出现新的实体时都要创建一个新方法。为了尝试实现这一点,我尝试了这样:

...

public static Class<T> resultList;
Class<T> entity;

...

public <T> void executiveQuery(String sql, Class<T> entity) {
    session = Base.getSessionFactory(url, username, password, entity).openSession();
    transaction = session.beginTransaction();
    query = session.createNativeQuery(sql, entity);
    resultList = (entity) query.getResultList().get(0); // 这一行上的实体无法编译
    session.close();
  }

我无法使该方法编译。我应该如何使 `executiveQuery()` 通用,以接受任何实体类,以便我可以像这样在 `returnList` 中获取数据库列:

public String getTestColmn() {
return resultList.getTestId();
}

然后调用 `executeQuery()` 并传递任何实体类给它,可能是这样的:

public void callExecuteQuery(String sql, Class<T> entity) {
    demoManager.executeQuery(sql, DemoEntity.class);
  }

我做错了什么?

如果您需要更多帮助或其他翻译,请告诉我。

英文:

I have this method that executes a native SQL query successfully. No issues. It maps the result list from the query to the relevant entity class:

@Data
public class DemoManager {

  Transaction transaction;
  static Session session;
  Query query;
  DemoEntity demoResultList;


  String url = &quot;...&quot;;
  String username = &quot;...&quot;;
  String password = &quot;...&quot;;
  Class&lt;DemoEntity&gt; demoEntity = DemoEntity.class;


  public void executiveQuery(String sql) {
    session = Base.getSessionFactory(url, username, password, demoEntity).openSession();
    transaction = session.beginTransaction();
    query = session.createNativeQuery(sql, demoEntity);
    demoResultList = (DemoEntity) query.getResultList().get(0);
    session.close();
  }

Now, the problem. I want to make the executeQuery() method generic, so that when it is called, any entity class can be passed as an argument, instead of creating a new method whenever there is a new entity. To try achieve that, I tried this:

...

public static Class&lt;T&gt;  resultList;
Class&lt;T&gt; entity;

...

public &lt;T&gt; void executiveQuery(String sql, Class&lt;T&gt; entity) {
    session = Base.getSessionFactory(url, username, password, entity).openSession();
    transaction = session.beginTransaction();
    query = session.createNativeQuery(sql, entity);
    resultList = (entity) query.getResultList().get(0); // the entity on this line could not be compiled
    session.close();
  }

I couldn't get that method to compile. How do I make the executiveQuery() generic to accept any entity class so that I can get my database column returned in returnList like this:

public String getTestColmn() {
return resultList.getTestId();

}

And then call executeQuery() and pass any entity class to it, perhaps something like this:

public void callExecuteQuery(String sql, Class&lt;T&gt; entity) {
    demoManager.executeQuery(sql, DemoEntity.class);
  }

What am I doing wrong?

答案1

得分: 1

要使方法通用,你需要使类也成为泛型。

public class DemoManager<T> {

 T resultList;

 @SuppressWarnings("unchecked")
 public void executiveQuery(String sql) {
    ...
    resultList = (T) query.getResultList().get(0);
    ...
 }
}

...

// 并且你需要更改创建 `DemoManager` 的方式
DemoManager<DemoEntity> demoManager = new DemoManager<>();
demoManager.executiveQuery(sql);
String testColumn = demoManager.getResultList().getTestColmn();

请注意,如果在进行类型转换时出现类型不匹配,它将在运行时抛出错误。


另一种选择是将 executiveQuery 设为静态方法,并将 session 和泛型类作为参数传递。

public class DemoManager {

 @SuppressWarnings("unchecked")
 public <T> static T executiveQuery(Session session, String sql, Class<T> entity) {
    transaction = session.beginTransaction();
    query = session.createNativeQuery(sql, demoEntity);
    return (T) query.getResultList().get(0);
 }
}

...

Session session = ...;
DemoEntity entity = DemoManager.executiveQuery(session, sql, DemoEntity.class);
String testColumn = entity.getTestColumn();
英文:

To make a method generic you need the class to be generic as well

public class DemoManager&lt;T&gt; {

 T resultList;

 @SuppressWarnings(&quot;unchecked&quot;)
 public void executiveQuery(String sql) {
    ...
    resultList = (T) query.getResultList().get(0);
    ...
 }
}

...

// And you need to change the creation of the `DemoManager`
DemoManager&lt;DemoEntity&gt; demoManager = new DemoManager&lt;&gt;(...);
demoManager.executiveQuery(sql);
String testColumn = demoManager.getResultList().getTestColmn();

Noting that if there is a type mismatch during the casting it will throw an error at runtime.


Another option is to have the executeQuery as static and get the session and the generic class as parameters

public class DemoManager {

 @SuppressWarnings(&quot;unchecked&quot;)
 public &lt;T&gt; static T executiveQuery(Session session, String sql, Class&lt;T&gt; entity) {
    transaction = session.beginTransaction();
    query = session.createNativeQuery(sql, demoEntity);
    return (entity) query.getResultList().get(0);
 }
}

...

Session session = ...;
DemoEntity entity = DemoManager.executiveQuery(session, sql, DemoEntity.class);
String testColumn = entity.getTestColumn();

huangapple
  • 本文由 发表于 2023年2月23日 23:44:45
  • 转载请务必保留本文链接:https://go.coder-hub.com/75547131.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定