JPA/Hibernate在EJB/Seam环境中提交时不发出更新
我有一个Seam 3沙箱应用程序,使用JBoss 7、Hibernate作为默认JPA实现和JSF作为web前端 我有一个问题,默认情况下SQL更新会被吞并 会话范围中的有状态EJB维护一个扩展范围的EntityManager和一个实体容器管理的事务(需要新的)JPA/Hibernate在EJB/Seam环境中提交时不发出更新,hibernate,ejb-3.0,jpa-2.0,seam3,jboss7.x,Hibernate,Ejb 3.0,Jpa 2.0,Seam3,Jboss7.x,我有一个Seam 3沙箱应用程序,使用JBoss 7、Hibernate作为默认JPA实现和JSF作为web前端 我有一个问题,默认情况下SQL更新会被吞并 会话范围中的有状态EJB维护一个扩展范围的EntityManager和一个实体容器管理的事务(需要新的) EntityManager被注入 EJB使用EM加载实体并将其保存在字段中 JSF应用程序访问EJB及其实体,更改字符串字段 JSF应用程序在EJB中调用“Save”方法 在save()中,我检查Entities字段是否已更改->是否已
@Named
@ConversationScoped
@Stateful
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public class LanguageBean {
@PersistenceContext(type = PersistenceContextType.EXTENDED)
private EntityManager em;
@Inject
private UserTransaction transaction;
private Language value;
@Inject
Conversation conversation;
public LanguageBean() {
super();
}
@Begin
public void selectLanguage(Long anId) {
conversation.setTimeout(10 * 60 * 1000);
if (anId != null) {
value = em.find(Language.class, anId);
}
}
@BeforeCompletion
public void transactionComplete(){
System.out.println("transactionComplete");
}
public Language getValue() {
return value;
}
@Produces
@Named
@ConversationScoped
public Language getLanguage() {
return getValue();
}
public void setValue(Language aValue) {
value = aValue;
}
@End
public String save() {
// displays the changed attribute:
System.out.println("save code: "+value.getCode());
// why is either this required:
// boolean tempContains = em.contains(value);
// System.out.println("managed: "+tempContains);
// or: why is persist required:
em.persist(value);
return "languages?faces-redirect=true";
}
@End
public String cancel() throws SystemException {
transaction.setRollbackOnly();
return "languages?faces-redirect=true";
}
}
尝试在由
@End
注释的方法上添加@删除注释
在我看来,@End
注释不会导致bean破坏。因此,即使在执行save()
之后,持久性上下文仍然处于活动状态,其内容无法刷新到数据库。我的经验主要是关于seam-2的,但在这里应该同样适用
会话和JPA会话在seam中是解耦的,原因很简单,会话结束可能不会导致实体被保存
例如,对长时间运行的对话执行取消操作将结束对话(因为没有理由再维护对话)
考虑到您在示例中正在对cancel进行回滚,您需要调用@user1187037建议的刷新(理论上是提交,但我认为这是不允许的)似乎也是合乎逻辑的
我认为可能有一个配置,您可以设置,使它在对话结束时刷新,但我可能弄错了
无论如何,这似乎是一个解决方案
希望有帮助
编辑:您可以使用xml配置每个会话的刷新模式
<begin-conversation join="true" flush-mode="COMMIT" />
但请记住,对话可以在没有明确定义的情况下@结束。如果用户在会话进行到一半时,对实体进行了更改,然后放弃了会话,则该会话将在超时后自动关闭。如果我没有记错,这将导致在上述情况下提交任何更改
参考资料:
http://docs.jboss.org/seam/3/latest/api/org/jboss/seam/persistence/FlushModeType.html我发现entityManager.flush()也解决了这个问题。但我不明白为什么这似乎是必要的。来自JPA规范:“当JTA事务提交时,提供程序必须将所有修改的实体状态刷新到数据库中。”也许hibernate会话的FlushMode设置为none?
@Begin(flushMode=COMMIT)