我已经在一个包含以下组件的项目上工作了一段时间:
- Struts2.1.8.1、
- Spring 3.0.3
- JPA 2.0、
- Hibernate 3
我正在使用 Spring 的 EntityManager 魔法...但是我在处理我的内部事务时遇到了问题行动。例如,我在类中的多个方法中设置持久对象的值,并且如果 validate
方法发现验证错误,我希望能够回滚
,或者否则提交
这些更改。我已经花了相当长的时间阅读了一半的互联网以获得全面的解释。不幸的是,不存在完整的示例(至少与我的堆栈类似)。
我在邮件列表上偶然发现了这个线程: Struts2 Action 中的 @Transactional Spring 注解不起作用。我链接的消息似乎有一个非常简单明了的解决方案,使用 TransactionInterceptor
似乎可以解决问题......问题是我没有找到有关此拦截器的有用信息。
这里的任何人都拥有这项技术的经验,并且可以提供有关如何在 Struts2 操作中使用 Spring 事务的提示和一两个链接吗?
谢谢!
- 编辑 1 -
如果您有兴趣,我已经设置了一个测试项目,只需 下载文件并尝试(或检查)。谢谢!
I have been working for a while on a project with the following components:
- Struts2.1.8.1,
- Spring 3.0.3
- JPA 2.0,
- Hibernate 3
I am using Spring's EntityManager magic... But I'm having problems dealing with transactions inside my actions. For instance, I am setting values on my persisted object in several methods within my class, and I want to be able to rollback
if the validate
method finds a validation error, or commit
these changes otherwise. I have already spent quite a long time reading half of the internet for a comprehensive explanation. Unfortunately, no complete examples exist (at least similar to my stack).
I have stumbled with this thread on a mailing list: @Transactional Spring Annotation in a Struts2 Action does not work. The message I'm linking at seems to have a pretty simple and straightforward solution, using a TransactionInterceptor
will do the trick it seems... The problem is that I'm not finding useful information regarding this interceptor.
Anyone here has experience with this technology and can spare a tip and a link or two on how to use Spring transactions inside Struts2 actions?
Thanks!
- Edit 1 -
I have set up a test project if you are interested, just download the file and try it out (or inspect it). Thanks!
发布评论
评论(3)
一般来说,控制器/操作/支持 bean 等不处理事务。操作是后端代码的 Web 部分 - 它们应该只关心收集请求数据和发送响应数据。逻辑本身(包括数据库访问)应该在另一层完成。例如服务层。因此,您创建另一个 bean,将其注入到操作中,并使其完成工作 -
userService.register(user)
。那么在服务层上配置事务应该是微不足道的,因为它既存在于 Spring 文档中,也存在于无数的示例中:
和@Transactional
(顺便说一句,请确保您现在有
,它可能会导致问题。即使它有效,这也不会使我关于服务层的建议无效)Generally, controllers/actions/backing beans/etc don't handle transactions. Actions are the web-part of your back-end code - they should only be concerned with gathering request data, and sending response data. The logic itself (including database access) should be done in another layer. E.g. a service layer. So you create another bean, inject it in the action, and make it do the work -
userService.register(user)
. Then configuring transactions on a service layer should be trivial since it is both in the spring documentation and in countless examples:<tx:annotation-driven />
and@Transactional
(btw, make sure you have the<tx:..>
now, it might be causing the issue. Even if it works, this does not invalidate my suggestion about the service layer)我不喜欢回答我自己的问题,但自从我很久以前解决这个问题......我认为我应该分享知识(或缺乏......在这种情况下)。
我用来学习 Struts 2 和 Spring-JPA-Hibernate 的书在服务类的声明之前添加了 @Transactional 注释。这是非常错误的,因为所有方法(包括那些仅从数据库检索内容的方法)都位于可提交事务内。长话短说,如果发生异常,所有事情都会发生。
正如博佐明智地指出的那样,解决方案是查看示例。也就是说,仔细设置你的事务方法,在我的例子中,我为必须写回数据库的方法设置了事务,一切都开始正常工作。
也感谢 Steven 和 Quaternion 花时间回答我的问题。
I don't like answering my own question, but since I solved this ages ago... I thought I should share the knowledge (or lack of... in this case).
The book I was using to learn about Struts 2 and Spring-JPA-Hibernate, adds the
@Transactional
annotation right before the declaration of the service class. This is terribly wrong, for all methods (including those that only retrieve stuff from the database) are inside a committable transaction. Long story short everything got committed event if exceptions occurred.The solution, as Bozho so wisely pointed out, was to look at examples. That is, set your transtactional methods carefully, in my case I set up transactions for the methods that had to write back to the database and everything started to work just fine.
Thanks to Steven and Quaternion too for taking the time to answer my question.
根据您的问题,我对您的问题的理解如下。
您希望将操作调用包装在事务中。如果 validate 方法记录了验证错误,则需要回滚事务。据推测,您还希望在发生错误时回滚。
解决方案
创建一个拦截器,它将:
您可能希望在堆栈的早期定义此拦截器。我不知道有任何为此目的预先构建的拦截器(尽管可能有一些),但它应该相当容易组装。
更新
我不使用Spring,所以我不能说JPA事务支持是如何工作的,但是你可以像这样处理你的EntityManager的事务:
这只是一个粗略的例子,但它应该说明重点。
Based on your question, here's what I understand about your problem.
You want to wrap your action invocation in a transaction. If the validate method records validation errors, you want to roll the transaction back. Presumably, you also want to rollback in case of an error.
Solution
Create an interceptor that will:
You will probably want this interceptor defined pretty early in the stack. I don't know of any pre-built interceptors for this (although there may be some), but it should be fairly easy to assemble.
Update
I don't use Spring, so I can't say how the JPA transaction support works there, but you can handle transactions for your EntityManager like:
This is just a crude example, but it should illustrate the point.