所以我正在审查几年前我参与的遗留项目。而且我发现了一些困扰我几天的事情。此应用程序使用两个不同的过滤器进行事务处一个名为 HibernateFilter 的过滤器和另一个名为 TransactionFilter 的过滤器(请参阅下面的代码)。
我的问题是: 为什么要使用第二个TransactionFilter?是不是HibernateFilter足够了?
我希望这里有人可以解释这个问题,或者是否有一些我不知道的事情。
HibernateFilter:
public void doFilter(ServletRequest request,
ServletResponse response,
FilterChain chain)
throws IOException, ServletException {
if (request.getAttribute(FILTER_APPLIED) == null) {
request.setAttribute(FILTER_APPLIED, FILTER_APPLIED);
applyFilter(request, response, chain);
} else {
chain.doFilter(request, response);
}
}
private void applyFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException {
try {
if (sf == null) {
log.info("SessionFactory assigned from XMLConfig!");
sf = XMLConfig.getSessionFactory();
}
log.debug("Starting a database transaction");
sf.getCurrentSession().beginTransaction();
// Call the next filter (continue request processing)
chain.doFilter(request, response);
// Commit and cleanup
log.debug("Committing the database transaction");
sf.getCurrentSession().getTransaction().commit();
} catch (Throwable ex) {
log.error("HibernateFilter, intressting error: " + getRequestUrl(request) + " " + ex, ex);
// Rollback only
try {
log.debug("Trying to rollback database transaction after exception");
sf.getCurrentSession().getTransaction().rollback();
} catch (Throwable rbEx) {
log.error("Could not rollback transaction after exception!", rbEx);
}
// Let others handle it... maybe another interceptor for exceptions?
throw new ServletException(ex);
}
}
TransactionFilter:
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
// Boot the session!!!
HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
HttpSession session = httpServletRequest.getSession(true);
session.setAttribute(this.getClass().getName(),"Session forced to start!");
// Start orion transaction...
Object attribute = servletRequest.getAttribute(FILTER_APPLIED);
if (attribute == null) {
servletRequest.setAttribute(FILTER_APPLIED, FILTER_APPLIED);
applyFilter(servletRequest, servletResponse, filterChain);
} else {// Skip filter if run more than once for a request.
filterChain.doFilter(servletRequest, servletResponse);
}
}
private void applyFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws ServletException {
TransactionManager manager = null;
try {
manager = (TransactionManager) new InitialContext().lookup("java:comp/UserTransaction");
if (manager != null) {
manager.begin();
}
} catch (NamingException e) {
LOG.error("Cant find TransactionManager!", e);
} catch (SystemException e) {
LOG.error("Error starting transaction!", e);
} catch (NotSupportedException e) {
LOG.error("begin() not supported!", e);
}
try {
filterChain.doFilter(servletRequest, servletResponse);
if (manager != null) {
manager.commit();
}
} catch (Exception e) {
try {
if (manager != null) {
manager.rollback();
// Let others handle the rest... maybe another interceptor for exceptions?
throw new ServletException(e);
}
} catch (SystemException e1) {
LOG.error("Couldn't rollback!", e1);
}
}
答案 0 :(得分:0)
为什么这样做有不同的选择,其中大多数只是当时没有人知道它。
但至少我可以给你一个部分有意义的场景。但在此之前我做了一些hibernate / JPA / JTA基础知识。
让我们了解它的使用原因。我假设有一个应用程序服务器在使用,其中配置了数据源并处理事务。例如JMS资源。另一方面,他们希望将hibernate用作持久性提供程序。现在有不同的选择,为什么他们不使用基于JPA的数据源和hibernate作为持久性提供程序。一个是应用程序服务器具有捆绑的JPA实现,团队无法否决/替换它。另一个是他们想要使用不属于JPA规范的hibernate自定义功能,并且他们无法将其与JPA方式结合使用。
总结一下,有很多选择,我的答案很多猜测,但我希望它至少有一点帮助。