【发布时间】:2018-11-01 20:54:05
【问题描述】:
我在 Spring 项目中使用 JPA(Hibernate)并问自己我的类“BooksHandler”(这是一个 DAO)是否是线程安全的?
我的应用配置代码:
@Configuration
@EnableTransactionManagement
public class AppConfig {
@Bean
public LocalContainerEntityManagerFactoryBean getEntityManagerFactory() {
LocalContainerEntityManagerFactoryBean emf = new LocalContainerEntityManagerFactoryBean();
emf.setDataSource(getDataSource());
emf.setPackagesToScan("jpa.models");
JpaVendorAdapter adapter = new HibernateJpaVendorAdapter();
emf.setJpaVendorAdapter(adapter);
emf.setJpaProperties(getProperties());
return emf;
}
@Bean
public DataSource getDataSource() {
DriverManagerDataSource dtSrc = new DriverManagerDataSource();
dtSrc.setDriverClassName("com.mysql.jdbc.Driver");
dtSrc.setUrl("jdbc:mysql://localhost:3306/jpa_example");
dtSrc.setUsername("dbuser1");
dtSrc.setPassword("dbuser1");
return dtSrc;
}
private Properties getProperties() {
Properties p = new Properties();
p.setProperty("hibernate.dialect", "org.hibernate.dialect.MySQL5Dialect");
p.setProperty("hibernate.hbm2ddl.auto", "create");
p.setProperty("hibernate.show_sql", "true");
return p;
}
//auto transaction management
@Bean
public PlatformTransactionManager getTransactionManager(EntityManagerFactory emf) {
JpaTransactionManager manager = new JpaTransactionManager();
manager.setEntityManagerFactory(emf);
return manager;
}
//auto exception management
@Bean
public PersistenceExceptionTranslationPostProcessor getPostProcessor() {
return new PersistenceExceptionTranslationPostProcessor();
}
}
DAO 类:
@Component
@Transactional
public class BooksHandler {
@PersistenceContext
private EntityManager em;
public Book createBook(String title, String isbn, int year) {
Book b = new Book();
b.setIsbn(isbn);b.setTitle(title);b.setYear(year);
em.persist(b);
System.out.println("book created: "+b.getId());
return b;
}
public Book getBook(int id) {
return em.find(Book.class, id);
}
//other CRUD methods
}
BooksHandler 的方法将被多个线程使用,我知道 EntityManager 本身不是线程安全的。但是我正在参加的在线课程就是这样做的。也许春天有一些幕后魔法让它线程安全?
【问题讨论】:
-
是的,它是线程安全的。 Spring 注入了一个代理,该代理委托给与当前事务/线程关联的 EM。见docs.spring.io/spring/docs/current/spring-framework-reference/…。这一切都在文档中进行了解释。
-
感谢您的回答!但是在文档中,他们使用 EntityManagerFactory (线程安全)来获取 EntityManager 执行操作,然后将其关闭并结束 CRUD 方法。在我的示例中,我直接使用 EntityManager 而不是来自工厂。它仍然是线程安全的吗?
-
多读第一句。我链接到的部分字面意思是:“注入的 JPA EntityManager 的行为类似于从应用程序服务器的 JNDI 环境中获取的 EntityManager,如 JPA 规范所定义的那样。它将所有调用委托给当前的事务性 EntityManager,如果有的话。否则,它会回退到每个操作新创建的 EntityManager,实际上使其使用线程安全。(强调我的)。该部分中的第 4 个示例 sn-p 显示了注入 EM 的用法。
-
好的,谢谢!
-
发布您的文字作为答案,它解决了我的问题
标签: java spring multithreading entitymanager