春季:在@ Component + @ Transactional类线程中使用EntitiyManager是否安全?

时间:2018-11-01 20:54:06

标签: java spring multithreading entitymanager

我正在Spring项目中使用JPA(休眠),并问自己我的类'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本身不是线程安全的。但是我正在参加的在线课程就是这样做的。也许在春天之前有一些魔术可以使线程安全吗?

2 个答案:

答案 0 :(得分:0)

如果线程安全,则表示您不会出现脏读不可重复读虚拟读的任何错误。不,这完全取决于您的事务隔离级别,该级别在您的Hibernate属性或每个@Transactional注释中进行配置。

否则,两个不同的会话或线程(如果使用的是@Async)可以同时访问相同的类方法并没有多大关系,因为最后,它完全取决于在您的隔离级别上。 blog很好地说明了何时使用哪种隔离级别。

答案 1 :(得分:0)

是的,它是线程安全的。 Spring注入一个代理,该代理委派给与当前事务/线程关联的EM。参见the documentation,其中说:

  

注入的JPA EntityManager的行为就像从JPA规范定义的从应用程序服务器的JNDI环境中获取的EntityManager一样。它将所有调用委派给当前的事务性EntityManager(如果有)。否则,它会退回到每个操作新创建的EntityManager,从而实际上使它的使用成为线程安全的

(重点是我的)。