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 的地方 顺便说一句。flush
和 clear
方法是多余的,如果你使用的是事务范围的 EntityManager
不管怎样,@stateless
注释上的 name
和 mappedName
属性也很可能是不必要的。
【参考方案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 的持久性不起作用的主要内容,如果未能解决你的问题,请参考以下文章