【问题标题】:When does EntityManager commit?EntityManager 何时提交?
【发布时间】:2011-10-26 15:20:51
【问题描述】:

我有以下服务...

@Stateless
@LocalBean
public class RandomService {

    @EJB RandomString stringTokenizer;

    @PersistenceContext
    EntityManager em;

    public String generate(Actions action)
    {
        Token token = new Token();
        token.setAction(action);
        token.setExpiry(new Date());
        token.setToken(stringTokenizer.randomize());

        em.persist(token);
        //em.flush();

        return String.format("%010d", token.getId()) + token.getToken();
    }
}

如果我不输入 em.flush(),那么 token.getId() 行将返回 null(使用 DB GENERATED SEQUENCE),尽管我知道如果我返回 Token 而不是字符串到调用服务的 id 已设置。因此,当服务返回令牌对象时,EM 似乎会刷新,但在我放入 String 时不会刷新。不过,通过冲洗,我得到了我需要的东西,对吗?

【问题讨论】:

    标签: jpa jersey ejb-3.1 entitymanager


    【解决方案1】:

    不要混淆刷新和提交。在flush() 期间,JPA 提供程序将生成的 SQL 物理发送到数据库,在您的情况下,读取生成的 ID 并将其填充到 bean 中。 请注意,您应该始终使用返回的实体,而不是传递给 persist() 的原始实体:

    token = em.persist(token);
    

    另一方面,提交执行数据库提交。显然它会首先触发flush(),但在这里对你没有帮助。但是既然你在问 - EJB 中的每个方法默认都是事务性的。这意味着当您将第一个 EJB 留在堆栈上时,事务将被提交:如果您从另一个 EJB 调用一个 EJB,则被调用方默认加入调用方事务(请参阅:事务传播行为)。

    另请注意,何时发送flush() 的规则有点复杂,因为每个提供商都会尽可能晚地分批执行此操作。

    【讨论】:

    • 我好像不能做 token = em.persist(token);使用 Netbeans 7.0.1 我猜这只是在最新的 EJB 中?
    • 我的错,返回新实例的是merge(),而不是persist()。不过,您需要明确地flush()
    • 谢谢。那么您对上述代码的看法是什么?我应该在调用者中就地或在更高级别进行格式化?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-28
    • 2016-01-10
    • 1970-01-01
    相关资源
    最近更新 更多