我正在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本身不是线程安全的。但是我正在参加的在线课程就是这样做的。也许在春天之前有一些魔术可以使线程安全吗?
答案 0 :(得分:0)
如果线程安全,则表示您不会出现脏读,不可重复读或虚拟读的任何错误。不,这完全取决于您的事务隔离级别,该级别在您的Hibernate属性或每个@Transactional
注释中进行配置。
否则,两个不同的会话或线程(如果使用的是@Async
)可以同时访问相同的类方法并没有多大关系,因为最后,它完全取决于在您的隔离级别上。 blog很好地说明了何时使用哪种隔离级别。
答案 1 :(得分:0)
是的,它是线程安全的。 Spring注入一个代理,该代理委派给与当前事务/线程关联的EM。参见the documentation,其中说:
注入的JPA EntityManager的行为就像从JPA规范定义的从应用程序服务器的JNDI环境中获取的EntityManager一样。它将所有调用委派给当前的事务性EntityManager(如果有)。否则,它会退回到每个操作新创建的EntityManager,从而实际上使它的使用成为线程安全的。
(重点是我的)。