对于每个实体,我都将创建一个控制器,一个服务和一个DAO。我现在有大约8个实体与这些课程。例如,以我的课程Categorie
和Product
为例。
类CategorieDaoImpl
实现了CategorieDao
中的方法
@Override
public boolean insertCategorie(Categorie categorie) {
Session session = null;
try {
session = super.getConnection();
session.getTransaction().begin();
session.save(categorie);
session.getTransaction().commit();
return true;
} catch (HibernateException e) {
e.printStackTrace();
return false;
} finally {
closeConnection(session);
}
}
类ProductDaoImpl
实现了ProductDao
中的方法
@Override
public boolean insertProduct(Product product) {
Session session = null;
try {
session = super.getConnection();
session.getTransaction().begin();
session.save(product);
session.getTransaction().commit();
return true;
} catch (HibernateException e) {
e.printStackTrace();
return false;
}
finally {
closeConnection(session);
}
}
如您所见,除了save()
的参数和参数外,这两个类的代码非常相似。
Intellij告诉我这是重复的代码,但是它没有像通常在类中包含重复的代码时那样为我提供解决方案。知道如何解决这个问题并将其变得更好吗?
谢谢。
编辑:
大多数Dao类具有相同的CRUS方法:获取,插入,更新,删除。通常,只有参数是不同的。
答案 0 :(得分:5)
您可以使用AbstractInsertable<T>
类来解决问题,该类具有一些public boolean insert(T t)
来保存您的代码:
public abstract class AbstractInsertable<T> extends ... {
public boolean insert(T t) {
Session session = null;
try {
session = super.getConnection();
session.getTransaction().begin();
session.save(t);
session.getTransaction().commit();
return true;
} catch (HibernateException e) {
e.printStackTrace();
return false;
} finally {
closeConnection(session);
}
}
[...]
}
然后,实现可以从该AbstractInsertable<T>
继承,例如CategorieDaoImpl extends AbstractInsertable<Category>
。当然,这仅在您仅继承一门课程的情况下才有效。
另一种选择是使用接口和默认实现。
答案在这里结束。剩下的就是我个人的看法。
我个人希望Java允许对这些确切问题进行多重继承:您可以为每个CRUD操作定义类,并将它们用作Dao
实现中的混合。接口中的默认方法非常接近多继承,但有一些限制,例如所有方法都必须为public
,并且无法定义属性,而多重继承则不会出现。
对您的代码稍作评论:您可能会出现NullPointerException
:
Session session = null;
try {
session = super.getConnection();
[...]
} finally {
closeSession(session);
}
在不知道closeSession(...)
的确切实现的情况下,如果您不执行nullcheck,那么可能会抛出NPE
,这不足为奇。如果Session
是AutoCloseable
,则可以使用try-with-resources
。如果不是,则可以使用Optional
来发挥自己的优势:
Optional<Session> optionalSession = Optional.empty();
try {
optionalSession = Optional.of(super.getConnection());
session = optionalSession.get();
[...]
} finally {
optionalSession.ifPresent(this::closeSession);
}
答案 1 :(得分:2)
最简单的解决方案是:
public boolean insertGeneric(Object whatever) {
Session session = null;
try {
session = super.getConnection();
session.getTransaction().begin();
session.save(whatever);
session.getTransaction().commit();
return true;
} catch (HibernateException e) {
e.printStackTrace();
return false;
} finally {
closeConnection(session);
}
}
当然,更“通用的答案”可能是您使用一些<T extends some BaseType>
类型的参数而不是Object
。
如果没有这样的基类,那么下一个最好的办法就是识别一个通用的基接口,或者是您打算保存的所有对象都可以/应该/需要实现的东西。
换句话说:您的选择空间在很大程度上取决于session.save()
的实际签名!