控制器在进行 spring/hibernate 调用时会阻塞吗?

Will controller block while making spring/hibernate call?

这是从 Play 和 Spring 示例的激活器模板创建项目后的控制器。

控制器代码:

@org.springframework.stereotype.Controller
public class Application {

    @Autowired
    private BarService barService;

    public Result addBar() {
        Form<Bar> form = Form.form(Bar.class).bindFromRequest();
        Bar bar = form.get();
        barService.addBar(bar);
        return play.mvc.Controller.redirect(controllers.routes.Application.index());
    }
}

酒吧服务:

@Service
@Transactional
public class BarServiceImpl implements BarService {

    @PersistenceContext
    EntityManager em;

    @Override
    public void addBar(Bar bar) {
        em.persist(bar);
    }

    @Override
    public List<Bar> getAllBars() {
        CriteriaQuery<Bar> c = em.getCriteriaBuilder().createQuery(Bar.class);
        c.from(Bar.class);
        return em.createQuery(c).getResultList();
    }
}

Spring 休眠配置:

@Configuration
@EnableTransactionManagement
public class DataConfig {

    @Bean
    public EntityManagerFactory entityManagerFactory() {
        HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
        vendorAdapter.setShowSql(true);
        vendorAdapter.setGenerateDdl(true);
        LocalContainerEntityManagerFactoryBean entityManagerFactory = new LocalContainerEntityManagerFactoryBean();
        entityManagerFactory.setPackagesToScan("models");
        entityManagerFactory.setJpaVendorAdapter(vendorAdapter);
        entityManagerFactory.setDataSource(dataSource());
        entityManagerFactory.setJpaPropertyMap(new HashMap<String, String>(){{
            put("hibernate.hbm2ddl.auto", "create-drop");
        }});
        entityManagerFactory.afterPropertiesSet();
        return entityManagerFactory.getObject();
    }

    @Bean
    public PlatformTransactionManager transactionManager() {
        JpaTransactionManager transactionManager = new JpaTransactionManager(entityManagerFactory());

        return transactionManager;
    }

    @Bean
    public DataSource dataSource() {
        final DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setDriverClassName(Play.application().configuration().getString("db.default.driver"));
        dataSource.setUrl(Play.application().configuration().getString("db.default.url"));
        return dataSource;
    }
}

我的问题是控制器调用 barService 中的 addBar 函数时是阻塞调用吗?如果是,那么在 Play 应用程序中进行 spring/hibernate 集成的正确方法应该是什么,因为它是来自 Typesafe 激活器本身的示例代码。

是的,它阻止了,因为 JDBC 没有 async/non-blocking 支持。由于 Hibernate 依赖于 JDBC,它继承了它的阻塞行为。这也是documented here:

Common examples of such blocking operations are JDBC calls, streaming API, HTTP requests and long computations.

我强烈建议您阅读以下文档页面:

  1. JavaAsync: Handling asynchronous results
  2. Understanding Play thread pools

我还建议您在这里查看其他非常相似的讨论: