控制器在进行 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.
我强烈建议您阅读以下文档页面:
我还建议您在这里查看其他非常相似的讨论:
这是从 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.
我强烈建议您阅读以下文档页面:
我还建议您在这里查看其他非常相似的讨论: