• understand EntityManager.joinTransaction()


    Join Transaction

    The EntityManager.joinTransaction() API allows an application managed EntityManager to join the active JTA transaction context. This allows an EntityManager to be created outside the JTA transaction scope and commit its changes as part of the current transaction. This is normally used with a stateful SessionBean, or with a JSP or Servlet where an EXTENDED EntityManager is used in a stateful architecture. A stateful architecture is one where the server stores information on a client connection until the client's session is over, it differs from a stateless architecture where nothing is stored on the server in between client requests (each request is processed on its own).

    There are pros and cons with both stateful and stateless architectures. One of the advantages with using a stateful architecture and and EXTENDED EntityManager, is that you do not have to worry about merging objects. You can read your objects in one request, let the client modify them, and then commit them as part of a new transaction. This is where joinTransaction would be used. One issue with this is that you normally want to create the EntityManager when there is no active JTA transaction, otherwise it will commit as part of that transaction. However, even if it does commit, you can still continue to use it and join a future transaction. You do have to avoid using transactional API such as merge or remove until you are ready to commit the transaction.

    joinTransaction is only used with JTA managed EntityManagers (JTA transaction-type in persistence.xml). For RESOURCE_LOCAL EntityManagers you can just commit the JPA transaction whenever you desire.

    Example joinTransaction usage

    EntityManager em = getEntityManagerFactory().createEntityManager();
    Employee employee = em.find(Employee.class, id);
    employee.setSalary(employee.getSalary() + 1000);
    
    UserTransaction transaction = (UserTransaction)new InitialContext().lookup("java:comp/UserTransaction");
    transaction.begin();
    em.joinTransaction();
    transaction.commit();

    参考:https://en.wikibooks.org/wiki/Java_Persistence/Transactions

    1.示例

    @Stateful
    public class ShoppingCartImpl implements ShoppingCart {
        @PersistenceUnit
        private EntityManagerFactory emf;
        private EntityManager em;
        private Order order;
        private Product product;
        @PostConstruct
        public void init() {
            em = emf.createEntityManager();
        }
        public void initOrder(Long id) {
            order = em.find(Order.class, id);
        }
        public void initProduct(String name) {
            product = (Product) em.createQuery("select p from Product p
                    where p.name = :name")
                    .setParameter("name", name)
                    .getSingleResult();
        }
        public LineItem createLineItem(int quantity) {
            em.joinTransaction();
            LineItem li = new LineItem(order, product, quantity);
            order.getLineItems().add(li);
            em.persist(li);
            return li;
        }
        @Remove
        public void destroy() {
            em.close();
        }
    }

    2.解析

    First, a few words of theory...

    An application-managed entity manager participates in a JTA transaction in one of two ways.

    1. If the persistence context is created inside the transaction, the persistence provider will automatically synchronize

    the persistence context with the transaction.
    2.If the persistence context was created earlier (outside of a transaction or in a transaction that has since ended), the

    persistence context can be manually synchronized with the transaction by calling joinTransaction() on the EntityManager

    interface. Once synchronized, the persistence context will automatically be flushed when the transaction commits.


    After reading the above definition a few questions may arise:

    1.how do we know that ShoppingCartImpl participates in JTA transaction ?

      Because the class has been annotated with @Stateful (or @Stateless) annotation so the intention is to execute the class

    within Java EE environment which by default uses JTA transactions. A class doesn't need such annotation, if it will be executed

    in Java SE environment.

    2.how do we know application-managed entity manager is used in this particular case?

    Because we are using @PersistenceUnit annotation to inject EntityManagerFactory and then manually creating and destroying

    EntityManager. By doing this we are telling Java EE container that we don't want our transaction to be automatically managed

    (like in case of transaction-scoped entity manager or extended entity manager types).

    3.why em.joinTransaction() is required in createLineItem method?

     By calling em.joinTransaction() we notify the application-managed persistence context that it should synchronize itself with the

    current JTA transaction. Without such call the changes to Order would not be flushed to the underlying database when the

    transaction commits (at the end of createLineItem method).

    NOTE: since EntityManagerFactory instances are thread-safe and EntityManager instances are not, an application must not call

    em.joinTransaction() on the same entity manager in multiple concurrent transactions.

    引用

    http://stackoverflow.com/questions/24442335/use-of-jointransaction-in-jpa

  • 相关阅读:
    人生,别认输,因为没人希望你赢
    一张图看懂开源许可协议,开源许可证GPL、BSD、MIT、Mozilla、Apache和LGPL的区别
    Android Studio 出现 Gradle's dependency cache may be corrupt 解决方案
    清华梦的粉碎——转自王垠
    label smooth
    <现代C++实战30讲>笔记 01 | 堆、栈、RAII:C++里该如何管理资源?
    h5转pb的两个坑
    opencv库的像素x,y,width,height,col,row的对应关系
    detect 导图
    keras多gpu训练
  • 原文地址:https://www.cnblogs.com/yuyutianxia/p/6343940.html
Copyright © 2020-2023  润新知