How I can get entitymanager from crudrepository
我使用Spring Boot并希望提高性能。 我必须在数据库中下载具有50000字段的文件。 使用休眠模式。 我在批处理插入中找到了解决方案。 但是我不知道如何从CrudRepository获得EntityManager
1 2 3 4 5 6 7 | public interface MyRepository extends CrudRepository<OTA, Long> application.yaml jdbc.batch_size: 50 order_inserts: true order_updates: true cache.use_second_level_cache: true |
我创建了MyStorageService并想保存我的文件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | @Service @Repository @Transactional public class MyStorageService { private MyRepository myRepository; private void insertAll(final List<MyFile> file) { myRepository.save(file.getListLine()); } private void insert(final List<OTA> ota) { Session session = (Session) entityManager.getDelegate(); Transaction tx = session.beginTransaction(); for (int i = 0; i < ota.size(); i++) { session.save(ota.get(i)); if (i % 50 == 0) { session.flush(); session.clear(); } } tx.commit(); session.close(); } |
}
如果在MyStorageService中使用
1 2 | @PersistenceContext EntityManager entityManager; |
我懂了
ERROR [http-nio-18842-exec-1] JpaTransactionManager: Commit exception
overridden by rollback exception java.lang.IllegalStateException:
Transaction not active at
org.hibernate.jpa.internal.TransactionImpl.getRollbackOnly(TransactionImpl.java:131)
at
org.springframework.orm.jpa.JpaTransactionManager$JpaTransactionObject.isRollbackOnly(JpaTransactionManager.java:665)ERROR [http-nio-18842-exec-1] JpaTransactionManager: Commit exception
overridden by rollback exception java.lang.IllegalStateException:
Transaction not active at
org.hibernate.jpa.internal.TransactionImpl.getRollbackOnly(TransactionImpl.java:131)
at
org.springframework.orm.jpa.JpaTransactionManager$JpaTransactionObject.isRollbackOnly(JpaTransactionManager.java:665)
如果
@Autowired
EntityManager实体管理器;
我懂了
ERROR [http-nio-18842-exec-5] JpaTransactionManager: Commit exception
overridden by rollback exception java.lang.IllegalStateException:
Transaction not active at
org.hibernate.jpa.internal.TransactionImpl.getRollbackOnly(TransactionImpl.java:131)
at
org.springframework.orm.jpa.JpaTransactionManager$JpaTransactionObject.isRollbackOnly(JpaTransactionManager.java:665)java.lang.IllegalStateException: EntityManager is closed at
org.hibernate.jpa.internal.EntityManagerImpl.checkOpen(EntityManagerImpl.java:97)
at
org.hibernate.jpa.internal.EntityManagerImpl.checkOpen(EntityManagerImpl.java:88)
at
org.hibernate.jpa.spi.AbstractEntityManagerImpl.clear(AbstractEntityManagerImpl.java:1382)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498) at
org.springframework.orm.jpa.ExtendedEntityManagerCreator$ExtendedEntityManagerInvocationHandler.invoke(ExtendedEntityManagerCreator.java:347)
at com.sun.proxy.$Proxy91.clear(Unknown Source) at
org.springframework.orm.jpa.JpaTransactionManager.doRollback(JpaTransactionManager.java:554)
我使用了来自crud存储库的基本方法
谢谢
我不确定您的spring配置如何设置。希望这会有所帮助,在这里您可以:
在这种情况下,如果在上下文xml或@Configuration java文件中设置了
假设您声明以上内容如下:
1 2 3 4 5 6 7 8 9 10 11 | <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> <property name="dataSource" ref="dataSourceRefToBeMentioned"/> <property name="packagesToScan" value="package.to.be.mentioned"/> <property name="jpaVendorAdapter" ref="hibernateJPAVendorAdapter"/> <property name="jpaProperties"> <props> <prop key="hibernate.dialect">org.hibernate.dialect.Oracle10gDialect</prop> <prop key="hibernate.show_sql">true</prop> </props> </property> </bean> |
现在,在您的服务类中,您可以如下所示自动装配LocalContainerEntityManagerManagerFactoryBean。
1 2 | @Autowired LocalContainerEntityManagerFactoryBean entityManagerFactory; |
在您想要访问实体管理器的方法中,可以执行以下操作:
1 | EntityManager entityManager = entityManagerFactory.getObject().createEntityManager(); |
在此之后,将遵循以下代码:
1 2 3 4 5 6 | Session session = (Session) entityManager.getDelegate(); Transaction tx = session.beginTransaction(); .... ... tx.commit(); session.close(); |
但是,请确保在完成整个事务后关闭entityManager,如下所示:
1 | entityManager.close(); |
希望这可以帮助。
从我的角度来看,存在几个潜在的问题。
- @Service和@Repository都是构造型注释,并允许Spring自动检测带注释的类并在上下文中注册。区别在于使用@Repository注释的类与PersistenceExceptionTranslationPostProcessor结合使用时可以进行Spring DataAccessException转换。
- 如果使用@Transactional为类添加注释,则需要确保CGLIB存在于类路径中,因为Spring AOP要求它为类创建代理。
- Spring AOP无法访问私有方法,这意味着当您使用@Transactional注释类时,其方法不在事务上下文中
因此,我建议将关注点分开,例如如果您想自己管理事务,请删除@Service和@Transactional等不必要的注释,但是根据您的代码,除非您在每个批处理完成后在for循环中提交,否则没有必要。
只需自动连线EntityManager
1 2 | @Autowired EntityManager entityManager; |