【问题标题】:Use JAX-RS and JPA with Tomcat without catch-finally将 JAX-RS 和 JPA 与 Tomcat 一起使用,无需 catch-finally
【发布时间】:2015-02-18 09:59:44
【问题描述】:

我们正在使用 JAX-RS 和 JPA。我们使用具有以下结构的方法(细节省略):

@PUT
@Path("{id}")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public ResultObject saveById(   @PathParam("id") BigInteger id, 
SomeObject someObject) {

    entityManager = EMF.obtainEntityManager();

    try {

      .. start transaction

      .. write all information to the database

      .. commit transaction

      .. return ResultObject
    } catch ( Exception exception) {

      .. rollback transaction

      .. return ResultObject together with an appropriate error
    } finally {
        entityManager.close();
    }           
}

有没有一种“最好的”方法来避免重复捕获并最终在我们创建的每个 JAX-RS 方法上重复?使用过滤器? 我们的服务提供者只支持 Tomcat。没有 Glassfish 或其他容器。 感谢您的帮助。

【问题讨论】:

    标签: java tomcat jpa jax-rs


    【解决方案1】:

    我会将实现转移到由 REST 服务调用的不同服务。 REST 应该是您的 API 的一种类型。逻辑应该在不同的服务中。

    @PUT
    @Path("{id}")
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.APPLICATION_JSON)
    public ResultObject saveById( @PathParam("id") BigInteger id, SomeObject someObject) {
        ResultObject resultObject = new ResultObject();
        ResultType res = someService.saveById(id, someObject)
        // do something with res
        return resultObject ;
    }
    

    然后在 SomeService 中会实现一些可以实现事务逻辑的抽象类。

    public abstract class AbstractService {
        protected void startTransaction() {
            //...
        }
        protected void endTransaction() {
            //...
        }
    }
    
    public class SomeService extends AbstractService {
       public ResultType saveById(BigInteger id, SomeObject someObject) {
           startTransaction();
           // your logic
           endTransaction();
       }
    }
    

    还有更好的方法。如果你知道的话,你可以使用 Spring Framework。 在该解决方案中,您使用 @Transactional 注释 SomeService(或该类中的方法)。

    @Transactional
    public class SomeService {
       public ResultType saveById(BigInteger id, SomeObject someObject) {
    
           // your logic
    
       }
    }
    

    【讨论】:

    • 感谢您的建议。我们一直在考虑。目前,我们的服务层由 JAX-RS 注释方法本身组成。在这个服务层后面,我们有一个组件层来处理所有的业务逻辑和数据库访问。 JAX-RS 注释的方法已经非常小了(平均可能有 5-10 个语句)。我们不知道在 JAX-RS 方法和组件层之间实现一个额外的服务层(只是为了摆脱 JAX-RS 方法中的 try-catch-finally 构造)是否值得。
    【解决方案2】:

    在过滤器中创建 EntityManger

    例如:-

    public class EntityManagerFilter implements Filter {
    
    
      public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
          throws IOException, ServletException {
        EntityManager em = null;
        try {
          /
          em = EntityManagerFactoryUtil.entityManagerFactory.createEntityManager();
         //
          EntityManagerUtil.ENTITY_MANAGERS.set(em);
          chain.doFilter(request, response);
          EntityManagerUtil.ENTITY_MANAGERS.remove();
          //
    
        } catch (Exception ex) {
          //
    
        } finally {
          try {
            if (em != null) {
              em.close();
              //
            };
          } catch (Throwable t) {
           //
          }
        }
      }
    
      public void init(FilterConfig config) {
        destroy();
        initEntityManagerFactory();
      }
    
      private void initEntityManagerFactory() {
        EntityManagerFactoryUtil.entityManagerFactory =
            Persistence.createEntityManagerFactory("PersistanceUnitName");
       //
    
      }
    
      public void destroy() {
       //
        try {
          if (EntityManagerFactoryUtil.entityManagerFactory != null) {
            EntityManagerFactoryUtil.entityManagerFactory.close();
          };
        } catch (Exception t) {
         /
      }
    }
    
    public class EntityManagerUtil {
    
    
    
     public static final ThreadLocal<EntityManager> ENTITY_MANAGERS = new ThreadLocal<EntityManager>();
    
      /** Returns a fresh EntityManager */
      public static EntityManager getEntityManager() {
        return ENTITY_MANAGERS.get();
      }
    
    }
    
    public class EntityManagerFactoryUtil {
    
      public static EntityManagerFactory entityManagerFactory;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-07-02
      • 2017-06-14
      • 1970-01-01
      • 2016-01-12
      • 1970-01-01
      • 2018-12-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多