如何在Java中避免具有相同方法主体但不同返回类型的重复代码?

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

How can I avoid duplicate code with the same method body but different return types in Java?

问题

以下是您提供的内容的翻译部分:

想法:

当我在使用 Hibernate 时,我发现每次都需要编写某种代码。所以我将它们移到另一个方法作为包装器。在那里,将会有一个作为参数的函数接口,这样我就可以在这些上下文方法中添加一些代码。

问题:

这是我的两个方法。一个返回 Object,而另一个返回 List。我如何精确地泛化并使这两个方法合为一个,以避免代码重复。

  1. public Object objectReturnContext(Function<Session, Object> function) {
  2. // ...
  3. }
  4. public List<T> listReturnContext(Function<Session, List<T>> function) {
  5. // ...
  6. }

更好地理解,这是我的整个类。如果有人能给我提供更好的方法,我将非常感激。我已经在这个问题上花了几天时间。

  1. package com.go_task.database;
  2. import javax.persistence.Table;
  3. // ... (其他 import 语句)
  4. public abstract class QueryExecutionContext <T> {
  5. // ...
  6. // (其他方法和属性)
  7. }

我已经在 BaseDaoImpl.java 中扩展了 QueryExecutionContext。所以我需要知道两件事。

  1. 我的方法是否可行。我在这里使用的是纯 Hibernate,没有使用 Spring Boot。
  2. 如果可以的话,请告诉我如何解决 objectReturnContext() 和 listReturnContext() 方法中的代码重复问题。
英文:

The Idea:

When I was using hibernate I saw that everytime I had to write some sort of code. So I moved them to another method as wrapper. Where there will be functional interface as argument so that I can append some code in those context methods.

Problem:

Here is my two methods. One returns Object while another one is returning List. How can I exactly generify and make those two methods as one so that I can avoid code duplication.

  1. public Object objectReturnContext(Function&lt;Session, Object&gt; function) {
  2. Object object = null;
  3. Transaction transaction = null;
  4. try {
  5. Session session = HibernateUtil.sessionFactory().getCurrentSession();
  6. transaction = session.beginTransaction();
  7. object = function.apply(session);
  8. transaction.commit();
  9. } catch (NoResultException exception) {
  10. if (transaction != null) transaction.rollback();
  11. return object;
  12. } catch (HibernateException exception) {
  13. if (transaction != null) transaction.rollback();
  14. exception.getStackTrace();
  15. }
  16. return object;
  17. }
  18. public List&lt;T&gt; listReturnContext(Function&lt;Session, List&lt;T&gt;&gt; function) {
  19. List&lt;T&gt; object = null;
  20. Transaction transaction = null;
  21. try {
  22. Session session = HibernateUtil.sessionFactory().getCurrentSession();
  23. transaction = session.beginTransaction();
  24. object = function.apply(session);
  25. transaction.commit();
  26. } catch (NoResultException exception) {
  27. if (transaction != null) transaction.rollback();
  28. return object;
  29. } catch (HibernateException exception) {
  30. if (transaction != null) transaction.rollback();
  31. exception.getStackTrace();
  32. }
  33. return object;
  34. }

For better understanding, This is my whole class. If anyone can advice me any better way I will be very thankful. I have been into this for last few days.

  1. package com.go_task.database;
  2. import javax.persistence.Table;
  3. import org.hibernate.HibernateException;
  4. import org.hibernate.Session;
  5. import org.hibernate.Transaction;
  6. import javax.persistence.NoResultException;
  7. import javax.persistence.criteria.CriteriaBuilder;
  8. import javax.persistence.criteria.CriteriaQuery;
  9. import javax.persistence.criteria.Root;
  10. import java.util.ArrayList;
  11. import java.util.List;
  12. import java.util.function.Consumer;
  13. import java.util.function.Function;
  14. public abstract class QueryExecutionContext &lt;T&gt; {
  15. public Class&lt;T&gt; entity;
  16. public String tableName;
  17. public QueryExecutionContext(Class&lt;T&gt; entity) {
  18. this.entity = entity;
  19. this.tableName = entity.getAnnotation(Table.class).name();
  20. }
  21. public List&lt;T&gt; criteriaContext(CriteriaContextRunner&lt;Session, Root&lt;T&gt;,
  22. CriteriaQuery&lt;T&gt;, CriteriaBuilder, List&lt;T&gt;&gt; runner) {
  23. List&lt;T&gt; data = new ArrayList&lt;&gt;();
  24. Transaction transaction = null;
  25. try {
  26. Session session = HibernateUtil.sessionFactory().getCurrentSession();
  27. transaction = session.beginTransaction();
  28. CriteriaBuilder criteriaBuilder = session.getCriteriaBuilder();
  29. CriteriaQuery&lt;T&gt; criteriaQuery =
  30. criteriaBuilder.createQuery(entity);
  31. Root&lt;T&gt; root = criteriaQuery.from(entity);
  32. data = runner.apply(session, root, criteriaQuery, criteriaBuilder);
  33. transaction.commit();
  34. } catch (HibernateException exception) {
  35. if (transaction != null) transaction.rollback();
  36. exception.getStackTrace();
  37. }
  38. return data;
  39. }
  40. public Object singleCriteriaContext(CriteriaContextRunner&lt;Session, Root&lt;T&gt;,
  41. CriteriaQuery&lt;T&gt;, CriteriaBuilder, Object&gt; runner) {
  42. Object data = null;
  43. Transaction transaction = null;
  44. try {
  45. Session session = HibernateUtil.sessionFactory().getCurrentSession();
  46. transaction = session.beginTransaction();
  47. CriteriaBuilder criteriaBuilder = session.getCriteriaBuilder();
  48. CriteriaQuery&lt;T&gt; criteriaQuery =
  49. criteriaBuilder.createQuery(entity);
  50. Root&lt;T&gt; root = criteriaQuery.from(entity);
  51. data = runner.apply(session, root, criteriaQuery, criteriaBuilder);
  52. transaction.commit();
  53. } catch (HibernateException exception) {
  54. if (transaction != null) transaction.rollback();
  55. exception.getStackTrace();
  56. }
  57. return data;
  58. }
  59. public Object objectReturnContext(Function&lt;Session, Object&gt; function) {
  60. Object object = null;
  61. Transaction transaction = null;
  62. try {
  63. Session session = HibernateUtil.sessionFactory().getCurrentSession();
  64. transaction = session.beginTransaction();
  65. object = function.apply(session);
  66. transaction.commit();
  67. } catch (NoResultException exception) {
  68. if (transaction != null) transaction.rollback();
  69. return object;
  70. } catch (HibernateException exception) {
  71. if (transaction != null) transaction.rollback();
  72. exception.getStackTrace();
  73. }
  74. return object;
  75. }
  76. public List&lt;T&gt; listReturnContext(Function&lt;Session, List&lt;T&gt;&gt; function) {
  77. List&lt;T&gt; object = null;
  78. Transaction transaction = null;
  79. try {
  80. Session session = HibernateUtil.sessionFactory().getCurrentSession();
  81. transaction = session.beginTransaction();
  82. object = function.apply(session);
  83. transaction.commit();
  84. } catch (NoResultException exception) {
  85. if (transaction != null) transaction.rollback();
  86. return object;
  87. } catch (HibernateException exception) {
  88. if (transaction != null) transaction.rollback();
  89. exception.getStackTrace();
  90. }
  91. return object;
  92. }
  93. public void noReturnContext(Consumer&lt;Session&gt; consumer) {
  94. Transaction transaction = null;
  95. try {
  96. Session session = HibernateUtil.sessionFactory().getCurrentSession();
  97. transaction = session.beginTransaction();
  98. consumer.accept(session);
  99. transaction.commit();
  100. } catch (HibernateException exception) {
  101. if (transaction != null) transaction.rollback();
  102. exception.getStackTrace();
  103. }
  104. }
  105. }

I have extented QueryExecutionContext in my BaseDaoImpl.java later on. So I need to know 2 things.

  1. Is my approch is ok or not. Im using pure hibernate and nothing else. No spring boot here.
  2. If so then tell me how can I solve the code duplication in objectReturnContext() and listReturnContext() method.

答案1

得分: 8

Object/List&lt;T&gt; 参数可以是泛型参数 U

  1. public <U> U returnContext(Function<Session, U> function) {
  2. U object = null;
  3. Transaction transaction = null;
  4. try {
  5. Session session = HibernateUtil.sessionFactory().getCurrentSession();
  6. transaction = session.beginTransaction();
  7. object = function.apply(session);
  8. transaction.commit();
  9. } catch (NoResultException exception) {
  10. if (transaction != null) transaction.rollback();
  11. return object;
  12. } catch (HibernateException exception) {
  13. if (transaction != null) transaction.rollback();
  14. exception.getStackTrace();
  15. }
  16. return object;
  17. }

U 将根据您传递给方法的 function 参数进行推断。如果像这样调用它:

  1. Object o = returnContext(s -> {
  2. ...
  3. return new Object(); // 仅为示例
  4. });

那么 U 就是 Object

如果像这样调用它:

  1. List<T> list = returnContext(s -> {
  2. ...
  3. return new ArrayList<T>(); // 仅为示例
  4. });

那么 U 就是 ArrayList<T>

英文:

The Object/List&lt;T&gt; parameter could be a generic parameter U:

  1. public &lt;U&gt; U returnContext(Function&lt;Session, U&gt; function) {
  2. U object = null;
  3. Transaction transaction = null;
  4. try {
  5. Session session = HibernateUtil.sessionFactory().getCurrentSession();
  6. transaction = session.beginTransaction();
  7. object = function.apply(session);
  8. transaction.commit();
  9. } catch (NoResultException exception) {
  10. if (transaction != null) transaction.rollback();
  11. return object;
  12. } catch (HibernateException exception) {
  13. if (transaction != null) transaction.rollback();
  14. exception.getStackTrace();
  15. }
  16. return object;
  17. }

U will be inferred depending on what function you pass into the method. If you call it like:

  1. Object o = returnContext(s -&gt; {
  2. ...
  3. return new Object(); // just an example
  4. });

Then U is Object.

If you call it like:

  1. List&lt;T&gt; list = returnContext(s -&gt; {
  2. ...
  3. return new ArrayList&lt;T&gt;(); // just an example
  4. });

Then U is ArrayList&lt;T&gt;.

huangapple
  • 本文由 发表于 2020年10月2日 21:04:00
  • 转载请务必保留本文链接:https://go.coder-hub.com/64172046.html
匿名

发表评论

匿名网友

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

确定