Java Hibernate事务和JTA
所以我在回顾我几年前参与的一个遗留项目。我注意到一些困扰了我几天的事情。此应用程序使用两个不同的筛选器进行事务处理。一个过滤器名为HibernateFilter,另一个过滤器名为TransactionFilter(请参阅下面的代码) 我的问题是:为什么要使用第二个TransactionFilter?HibernateFilter还不够吗 我希望这里有人能解释这一点,或者如果我遗漏了什么 休眠过滤器:Java Hibernate事务和JTA,java,hibernate,jta,Java,Hibernate,Jta,所以我在回顾我几年前参与的一个遗留项目。我注意到一些困扰了我几天的事情。此应用程序使用两个不同的筛选器进行事务处理。一个过滤器名为HibernateFilter,另一个过滤器名为TransactionFilter(请参阅下面的代码) 我的问题是:为什么要使用第二个TransactionFilter?HibernateFilter还不够吗 我希望这里有人能解释这一点,或者如果我遗漏了什么 休眠过滤器: public void doFilter(ServletRequest request
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);
}
}
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);
}
}
TransactionFilter:
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);
}
}
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);
}
}
为什么要这样做,有不同的选择,大多数都是当时没有人知道的 但至少我可以给你一个场景,在这个场景中,这部分是有意义的。但在此之前,我要介绍一些hibernate/JPA/JTA的基本原理
总而言之,有很多选择,我的答案是很多猜测,但我希望它至少有一点帮助 正如我正确理解的那样,第一个处理数据库事务,而不考虑通过低级HibernateAPI关闭任何用户会话。第二种方法强制每个请求都有一个用户会话,该请求在开始和结束时启动和提交。关于环境,这是运行第二个应该会导致与第一个相同的行为。