Play2如何从服务层而不是动作层管理事务?

时间:2013-08-31 07:55:47

标签: jpa playframework-2.0

我正在使用Play2.1.1 Java和JPA2.0以及hibernate实现。

通过代码来控制事务而不是像下面这样使用@transactional是正常的JPA代码风格,有没有办法像Play下面那样工作?或者如何使用JPA.withtranaction()来做?我试过了,不知道如何传递参数,我不熟悉功能代码。非常感谢。请根据以下内容给我一些示例代码。

public  void createActorB(final String email, final String psw) throws Throwable {
    EntityManager manager = JPA.em();
    try {
        EntityTransaction ex = manager.getTransaction();
        this.dbActor.setEmail(email);
        this.dbActor.setCredential(psw);
        manager.persist(this.dbActor);
        ex.commit();
    } catch (Exception e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
        throw new ActorException(CODE.UNKNOWN, e);
    } finally {
        manager.close();
    }
}

现在我更改下面的代码以从服务层启动事务,它看起来效率不高,有没有其他方法可以编写?感谢

private void internalCreateActor(String email, String psw) throws ActorException {
        if (StringUtils.isEmpty(email) || StringUtils.isEmpty(psw))
            throw new ActorException(CODE.INVALIDE_PARAMETER);
        try {
            this.dbActor.setEmail(email);
            this.dbActor.setCredential(psw);
            this.dbActor.setCreateD(new Date());
            JPA.em().persist(this.dbActor);
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            throw new ActorException(CODE.UNKNOWN, e);
        }
    }

 public void createActor(final String email, final String psw, final String cellPhone, final Actor.TYPE type)
            throws Throwable {

        JPA.withTransaction(new Callback0() {
            @Override
            public void invoke() throws Throwable {
                internalCreateActor(email, psw, cellPhone, type);
            }
        });
    }

2 个答案:

答案 0 :(得分:1)

类似的东西:

public static User getUserByIdentity(final AuthUserIdentity identity) {
    try {
        return JPA.withTransaction(new play.libs.F.Function0<User>() {
            public User apply() {       
                return User.findByAuthUserIdentity(identity);
            }
        });
    } catch (Throwable t) {
        throw new RuntimeException(t);
    }       
}

答案 1 :(得分:0)

经过一段时间的研究,我编写了一个方法JPAUtil,引用了Play提供的JPA,它可以正常地从服务层手动控制事务处理。

public class JPAUtil {

    static ThreadLocal<EntityManager> currentEntityManager = new ThreadLocal<EntityManager>();

    /**
     * Get the EntityManager for specified persistence unit for this thread.
     */
    public static EntityManager em(String key) {
        Application app = Play.application();
        if (app == null) {
            throw new RuntimeException("No application running");
        }

        JPAPlugin jpaPlugin = app.plugin(JPAPlugin.class);
        if (jpaPlugin == null) {
            throw new RuntimeException("No JPA EntityManagerFactory configured for name [" + key + "]");
        }

        EntityManager em = jpaPlugin.em(key);
        if (em == null) {
            throw new RuntimeException("No JPA EntityManagerFactory configured for name [" + key + "]");
        }

        bindForCurrentThread(em);

        return em;
    }

    /**
     * Get the default EntityManager for this thread.
     */
    public static EntityManager em() {
        EntityManager em = currentEntityManager.get();
        if (em == null) {
            return em(Constants.DATASOURCEKEY);
        }
        return em;
    }

    /**
     * Bind an EntityManager to the current thread.
     */
    public static void bindForCurrentThread(EntityManager em) {
        currentEntityManager.set(em);
    }

    public static void closeEM() {
        EntityManager em = currentEntityManager.get();
        if (em != null) {
            em.close();
        }
        bindForCurrentThread(null);
    }

    public static void beginTransaction() {
        em().getTransaction().begin();
    }

    public static void commitTransaction() {
        em().getTransaction().commit();
    }

}