JPA/Hibernate在EJB/Seam环境中提交时不发出更新

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字段是否已更改->是否已

我有一个Seam 3沙箱应用程序,使用JBoss 7、Hibernate作为默认JPA实现和JSF作为web前端

我有一个问题,默认情况下SQL更新会被吞并

会话范围中的有状态EJB维护一个扩展范围的EntityManager和一个实体容器管理的事务(需要新的)

  • EntityManager被注入
  • EJB使用EM加载实体并将其保存在字段中
  • JSF应用程序访问EJB及其实体,更改字符串字段
  • JSF应用程序在EJB中调用“Save”方法
  • 在save()中,我检查Entities字段是否已更改->是否已正确更改
  • 我什么也不做,容器在save()完成后提交事务
  • 问题:没有对数据库执行SQL更新
  • 如果通过以下方式扩展save():

    a) 包含(实体)按预期执行更新(结果为“true”)

    b) persist(实体)按预期执行更新

    问:据我所知,规范a)或b)都不需要,因为实体在整个过程中都处于管理状态。 我不明白,为什么a)对储蓄有影响。 我可以想象b)对保存有影响,但它不应该是必需的,对吗

    欢迎任何解释

    这是我的EJB:

    @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)