【问题标题】:Commit EntityManager Transaction using @Transactional - Guice使用 @Transactional 提交 EntityManager 事务 - Guice
【发布时间】:2016-07-18 04:40:20
【问题描述】:

我正在使用 Guice 来注入 EntityManager。 当我提交注入 entityManager 的事务时,BD 端没有发生任何事情:没有事务通过!!!你能帮我弄清楚发生了什么吗?

这是我的代码:

Web.xml

  <filter>
    <filter-name>guiceFilter</filter-name>
    <filter-class>com.google.inject.servlet.GuiceFilter</filter-class>
    <async-supported>true</async-supported>
  </filter>

  <filter-mapping>
    <filter-name>guiceFilter</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>

  <listener>
    <listener-class>ca.products.services.InjectorListener</listener-class>
  </listener>

InjectorListener 类:

public class InjectorListener extends GuiceServletContextListener {
    @Override
    protected Injector getInjector() {

        return Guice.createInjector(
                new PersistenceModule(),
                new GuiceModule(),
                new RestModule());
    }
}

persistenceModule 类:

public class PersistenceModule implements Module {
    @Override
    public void configure(Binder binder) {
        binder
                .install(new JpaPersistModule("manager1")
                        .properties(getPersistenceProperties()));

        binder.bind(PersistenceInitializer.class).asEagerSingleton();
    }

    private static Properties getPersistenceProperties() {
        Properties properties = new Properties();
        properties.put("hibernate.connection.driver_class", "org.postgresql.Driver");
        properties.put("hibernate.connection.url", "jdbc:postgresql://localhost:5432/postgres");
        properties.put("hibernate.connection.username", "postgres");
        properties.put("hibernate.connection.password", "postgres");
        properties.put("hibernate.connection.pool_size", "1");
        properties.put("hibernate.dialect", "org.hibernate.dialect.PostgreSQLDialect");
        properties.put("hibernate.hbm2ddl.auto", "create");

        return properties;
    }
}

GuiceModule 类:

public class GuiceModule extends AbstractModule {

    @Override
    protected void configure() {

        bind(MemberRepository.class).to(MemberRepositoryImp.class);
        bind(ProductRepository.class).to(ProductRepositoryImpl.class);
        bind(ShoppingBagRepository.class).to(ShoppingBagRepositoryImpl.class);
    }
}

RestModule 类:

公共类 RestModule 扩展 JerseyServletModule {

    @Override
    protected void configureServlets() {

        HashMap<String, String> params = new HashMap<>();
        params.put(PackagesResourceConfig.PROPERTY_PACKAGES, "ca.products.services");
        params.put(JSONConfiguration.FEATURE_POJO_MAPPING, "true");
        params.put(ResourceConfig.FEATURE_DISABLE_WADL, "true");

        serve("/*").with(GuiceContainer.class, params);
    }
} 

最后是 webservice (jeresy) 调用:

    @Inject
    private Provider<EntityManager> em;

    @GET
    @Transactional
    @Path("/reset")
    public void resetData() {

        logger.info("Processing reset");
        try {

            em.get().getTransaction().begin();

            for (int i = 0; i < 10; i++) {
                em.get().persist(new Product("Product_" + i, "Desc_" + i));
            }
            em.get().flush();
            em.get().getTransaction().commit();

        } catch (Exception e) {
            throw new WebApplicationException(Response.Status.FORBIDDEN);
        }
    }

【问题讨论】:

    标签: dependency-injection jersey persistence guice entitymanager


    【解决方案1】:

    您可能需要添加持久过滤器。这也将使您不必手动管理交易。如果您不使用过滤器,您仍然可以注入 UnitOfWork 来创建事务。如果您使用的是 jpa persist,则不应管理 userTransactions。

    这是一个自定义过滤器,它还添加了一个生命周期,它在启动时使用一些自定义代码和一个地图活页夹构建器自动启动。它只是为了彻底。它不是 guice api 的一部分,但更类似于 spring 的 Lifecycle 监听器。我根本没有任何 spring 依赖项。

    @Singleton
    public final class JpaPersistFilter implements Filter {
    
        private final UnitOfWork unitOfWork;
        private final PersistServiceLifecycle persistService;
    
        @Inject
        public JpaPersistFilter(UnitOfWork unitOfWork, PersistServiceLifecycle persistService) {
            this.unitOfWork = unitOfWork;
            this.persistService = persistService;
        }
    
        public void init(FilterConfig filterConfig) throws ServletException {
            // persistService.start();
        }
    
        public void destroy() {
            persistService.stop();
        }
    
        public void doFilter(final ServletRequest servletRequest, final ServletResponse servletResponse,
                final FilterChain filterChain) throws IOException, ServletException {
    
            unitOfWork.begin();
            try {
                filterChain.doFilter(servletRequest, servletResponse);
            } finally {
                unitOfWork.end();
            }
        }
    
        /**
         * Extra lifecycle handler for starting and stopping the service. This
         * allows us to register a {@link Lifecycle} with the
         * {@link LifecycleListener} and not have to worry about the service being
         * started twice.
         * 
         * @author chinshaw
         *
         */
        @Singleton
        public static class PersistServiceLifecycle implements Lifecycle {
    
            private final PersistService persistService;
    
            private volatile boolean isStarted = false;
    
            @Inject
            public PersistServiceLifecycle(PersistService persistSerivce) {
    
                this.persistService = persistSerivce;
            }
    
            @Override
            public boolean isRunning() {
                return isStarted;
            }
    
            @Override
            public void start() {
                if (!isStarted) {
                    persistService.start();
                    isStarted = true;
                }
            }
    
            @Override
            public void stop() {
                persistService.stop();
                isStarted = false;
            }
        }
    }
    

    向模块添加过滤器的示例。

    @Override
    protected void configureServlets() {
        filter("/api/*").through(JpaPersistFilter.class);
    }
    

    使用工作单元管理事务的示例。

    @Inject
    UnitOfWork unitOfWork;
    public void doSomething() {
        unitOfWork.begin();
        try {
             dao.saveState(someobject);
        } finally {
            unitOfWork.end();
        }
    }
    

    【讨论】:

    • 嗨,克里斯,我添加了一个简单的 GuiceFilter 并且它可以工作 ;) : filter("/*").through(PersistFilter.class);谢谢
    猜你喜欢
    • 2021-06-06
    • 1970-01-01
    • 1970-01-01
    • 2014-04-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-31
    • 2013-08-08
    相关资源
    最近更新 更多