EJB3 的持久性不起作用

Posted

技术标签:

【中文标题】EJB3 的持久性不起作用【英文标题】:Persistence with EJB3 doesn't work 【发布时间】:2012-11-22 15:59:23 【问题描述】:

我有一个方法可以在 EJB bean 中保存一个新对象。调用此方法,没有错误,但数据库中没有任何变化。我不明白为什么。

代码如下:

@Stateless(name = "Ar", mappedName = "ManagementBean")
public class ManagementBean implements IManagementBeanLocal, IManagementBeanRemote 
...
    @Override
    public int storeRawSms(String raw, String requestUid, String text, String service, boolean correctlyAnalysed, Date receivedTimestamp,
            boolean toBeAnalysed, String phoneNumber) 

        // Get phone number, create if it dosn't exist
        PhoneNumber pn = getOrCreatePhoneNumberPrivate(phoneNumber);

        // Create rawSMS
        RawSms rawSms = new RawSms(raw, requestUid, text, service, correctlyAnalysed, receivedTimestamp, toBeAnalysed, pn);

        // Store and return result
        em.persist(rawSms);
        int result =  rawSms.getId();

        em.flush();
        em.clear();

        return result;
    

...

和调用者:

@PersistenceContext private EntityManager em; 
... 
int rawSmsIs = bean.storeRawSms(raw, requestUid, message, service, false, new Date(), true, sender);

你有什么想法吗?

【问题讨论】:

你检查生成的SQL了吗?你能在调试器中单步执行该方法吗? 在注入 ManagementBean 和调用方法的位置添加代码。还有你注入 em 的地方 顺便说一句。 flushclear 方法是多余的,如果你使用的是事务范围的 EntityManager 不管怎样,@stateless 注释上的 namemappedName 属性也很可能是不必要的。 【参考方案1】:

我看到您在客户端中注入了对 EntityManager 的引用(不知道为什么),但我在会话 bean 中没有看到它(可能只是因为您没有在消息中包含该行)。您是否可能忘记在无状态会话 bean 中使用注解 @PersistenceContext?

另外,请注意:根据您使用的 JPA 实现和 id 的生成策略,您应该 调用 getId() 之前调用 flush()。实际上,如果您让数据库生成您的 ID,那么您需要一个 flush() 在方法返回值之前发生这种情况。

【讨论】:

【参考方案2】:

谢谢,建议的解决方案奏效了!

我像这样使用容器管理的事务:

@Stateless(name = "Ar", mappedName = "ManagementBean")
@TransactionManagement(TransactionManagementType.CONTAINER)
public class ManagementBean implements IManagementBeanLocal, IManagementBeanRemote 
....
    @Override
    @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
    public int storeRawSms(String raw, String requestUid, String text, String service, boolean correctlyAnalysed, Date receivedTimestamp, boolean toBeAnalysed, String phoneNumber) 
....

再次感谢!

【讨论】:

【参考方案3】:

您的事务似乎从未提交,因此请尝试更改事务管理:

@Stateless(name = "Ar", mappedName = "ManagementBean")
@TransactionManagement(TransactionManagementType.BEAN)
public class ManagementBean implements IManagementBeanLocal, IManagementBeanRemote 

      @Resource
      private UserTransaction utx;

      @Override
      public int storeRawSms(..) 

            try 
                  utx.begin();
                  ..
                  em.persist(rawSms);
                  int result =  rawSms.getId();
                  utx.commit();
            
            catch(Exception ex) 
                  //EXCEPTION HANDLING
                  utx.rollback();
            
      

【讨论】:

这将是一个很好的实验。如果这可行,那么问题肯定是容器管理的事务没有被提交。但是,对于真正的修复,我认为最好让容器管理的事务正常工作,而不是使用 bean 管理的事务。应该没有必要使用 bean 管理的事务,而且会更难维护。 我已经多次看到这种(错误)行为,这就是为什么我建议尝试“手动”事务管理的原因。同意,长期依赖容器管理的事务会更好。 投了反对票的人,请解释一下。这真的可能是问题的解决方案。 嗨,这是问题的解决方案。根据响应中的建议,我使用 ctx.begin 和 ctx.commit 尝试了 bean 管理的事务。没关系!接下来,我尝试了容器管理事务的解决方案,并使用 REQUIRES-NEW 作为参数,一切正常。谢谢! 非常好,很高兴为您提供帮助。这是我第一次以 -1 票获得接受的答案:D

以上是关于EJB3 的持久性不起作用的主要内容,如果未能解决你的问题,请参考以下文章

React Native - Firebase 身份验证持久性不起作用

TommEE 会话持久存储不起作用

Qtwebkit 持久性 Cookie 不起作用

Spring安全令牌持久性存储不起作用

Cookie 持久性在 OWIN 身份验证中不起作用

持久性 EHcache 文档中的代码不起作用 java