如果可能的话,我想要的只是一个“快速而干净”的解决方案,所以现在没有新的框架(不过我可能稍后会使用 Spring+Hibernate 堆栈)。
所以我最终使用了一个“快速且不那么脏”的解决方案,其中涉及“命令”模式的变体,其中休眠调用被封装在实现我的通用命令接口的匿名内部类中,命令执行器包装使用 Hibernate 会话和异常处理进行调用。通用位是为了让执行方法具有不同的返回值类型。
我对这个解决方案不是 100% 满意,因为它仍然意味着一些样板代码围绕着我的业务逻辑(我对返回值所需的显式转换特别不满意)并且它使得理解和调试稍微复杂一些。
然而,重复代码的收益仍然很大(从大约 10 行到每个方法 3-4 行),更重要的是 Hibernate 处理逻辑集中在一个类中,因此如果需要可以轻松更改它,并且错误更少 -易于。
这是一些代码:
命令界面:
public interface HibernateCommand<T> {
public T execute(Object... args) throws Exception;
}
执行者:
public class HibernateCommandExecuter {
private static final Logger logger = Logger.getLogger(HibernateCommandExecuter.class);
public static Object executeCommand(HibernateCommand<?> command, boolean commit, Object... args) throws RemoteException{
try {
HibernateUtil.currentSession().beginTransaction();
return command.execute(args);
} catch (HibernateException e) {
logger.error("Hibernate problem : ", e);
throw new RemoteException(e.getMessage());
}catch(Exception e){
throw new RemoteException(e.getMessage(), e);
}
finally {
try{
if(commit){
HibernateUtil.currentSession().getTransaction().commit();
}else{
HibernateUtil.currentSession().getTransaction().rollback();
}
HibernateUtil.currentSession().close();
}catch(HibernateException e){
logger.error("Error while trying to clean up Hibernate context :", e);
}
}
}
}
远程调用方法中的示例使用(但也可以在本地使用):
@Override
public AbstractTicketingClientDTO doSomethingRemotely(final Client client) throws RemoteException {
return (MyDTO) HibernateCommandExecuter.executeCommand(new HibernateCommand<MyDTO>() {
public AbstractTicketingClientDTO execute(Object...args) throws Exception{
MyDTO dto = someService.someBusinessmethod(client);
return dto;
}
},false);
}
请注意客户端参数是如何声明为 final 的,因此可以在内部类中引用它。如果无法声明 final,则可以将其作为参数传递给 executeCommand 方法。