我如何从 crudrepository 获取 entitymanager

Posted

技术标签:

【中文标题】我如何从 crudrepository 获取 entitymanager【英文标题】:How I can get entitymanager from crudrepository 【发布时间】:2017-11-03 23:55:44 【问题描述】:

我使用 Spring Boot 并希望提高性能。我必须下载数据库中包含 50000 字段的文件。使用休眠。我在Batch inserts 中找到了解决方案。但我不知道如何从 crudrepository 获取 entitymanager

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 并想保存我的文件:

@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 中使用

@PersistenceContext
EntityManager entityManager;

我明白了

错误 [http-nio-18842-exec-1] JpaTransactionManager:提交异常 被回滚异常 java.lang.IllegalStateException 覆盖: 交易不活跃于 org.hibernate.jpa.internal.TransactionImpl.getRollbackOnly(TransactionImpl.java:131) 在 org.springframework.orm.jpa.JpaTransactionManager$JpaTransactionObject.isRollbackOnly(JpaTransactionManager.java:665)

错误 [http-nio-18842-exec-1] JpaTransactionManager:提交异常 被回滚异常 java.lang.IllegalStateException 覆盖: 交易不活跃于 org.hibernate.jpa.internal.TransactionImpl.getRollbackOnly(TransactionImpl.java:131) 在 org.springframework.orm.jpa.JpaTransactionManager$JpaTransactionObject.isRollbackOnly(JpaTransactionManager.java:665)

如果

@Autowired 实体管理器实体管理器;

我明白了

错误 [http-nio-18842-exec-5] JpaTransactionManager:提交异常 被回滚异常 java.lang.IllegalStateException 覆盖: 交易不活跃于 org.hibernate.jpa.internal.TransactionImpl.getRollbackOnly(TransactionImpl.java:131) 在 org.springframework.orm.jpa.JpaTransactionManager$JpaTransactionObject.isRollbackOnly(JpaTransactionManager.java:665)

java.lang.IllegalStateException: EntityManager 关闭于 org.hibernate.jpa.internal.EntityManagerImpl.checkOpen(EntityManagerImpl.java:97) 在 org.hibernate.jpa.internal.EntityManagerImpl.checkOpen(EntityManagerImpl.java:88) 在 org.hibernate.jpa.spi.AbstractEntityManagerImpl.clear(AbstractEntityManagerImpl.java:1382) 在 sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 在 sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) 在 sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 在 java.lang.reflect.Method.invoke(Method.java:498) 在 org.springframework.orm.jpa.ExtendedEntityManagerCreator$ExtendedEntityManagerInvocationHandler.invoke(ExtendedEntityManagerCreator.java:347) 在 com.sun.proxy.$Proxy91.clear(Unknown Source) 在 org.springframework.orm.jpa.JpaTransactionManager.doRollback(JpaTransactionManager.java:554)

我使用来自 crud 存储库的基本方法 save,但想提高性能并使用插入。请告诉。 谢谢

【问题讨论】:

Spring boot - configure EntityManager的可能重复 another solution 【参考方案1】:

我不确定您的弹簧配置是如何设置的。希望这可能会有所帮助,请继续:

如果你已经在你的上下文xml或者@Configuration java文件中设置了org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean的bean,那么你可以通过以下方式获取实体管理器。

假设您将上述声明如下:

<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>

现在在您的服务类中,您可以自动装配 LocalContainerEntityManagerFactoryBean,如下所示。

@Autowired
LocalContainerEntityManagerFactoryBean entityManagerFactory;

在您想要访问实体管理器的方法中,您可以执行以下操作:

EntityManager entityManager = entityManagerFactory.getObject().createEntityManager();

在此之后,将遵循以下代码:

Session session = (Session) entityManager.getDelegate();
Transaction tx = session.beginTransaction();
....
...
tx.commit();
session.close();

但是,请确保在完成整个事务后关闭 entityManager,如下所示:

entityManager.close();

希望这会有所帮助。

【讨论】:

很高兴,它有帮助。【参考方案2】:

在我看来有几个潜在的问题。

@Service 和@Repository 都是原型注解,允许 Spring 自动检测注解的类并在上下文中注册。不同之处在于,当与 PersistenceExceptionTranslationPostProcessor 一起使用时,使用 @Repository 注释的类符合 Spring DataAccessException 转换的条件。 如果您使用 @Transactional 注释类,则需要确保 CGLIB 存在于您的类路径中,因为 Spring AOP 要求它为类创建代理。 Spring AOP 无法访问私有方法,这意味着当您使用 @Transactional 注释类时,它的方法不在事务上下文中

所以我建议将关注点分开,例如如果您想自己管理事务,请删除不必要的注释,例如 @Service 和 @Transactional,但是根据您的代码,除非您在每个批处理完成后在 for 循环中提交,否则没有必要。

【讨论】:

【参考方案3】:

只需自动装配 EntityManager

@Autowired
EntityManager entityManager;

【讨论】:

感谢您的回答,但它不适用于我的情况。我更新了我的问题

以上是关于我如何从 crudrepository 获取 entitymanager的主要内容,如果未能解决你的问题,请参考以下文章

如何使用CrudRepository避免额外的json获取记录

Groovy 和 JPA 阻止 Spring Boot CrudRepository 进行插入

我的自定义存储库实现中的 CrudRepository

在我的情况下,如何编写自定义 CrudRepository 方法(@Query)来过滤结果

如何修复CrudRepository.save(java.lang.Object)是springboot中的无法访问方法?

CrudRepository findOne() 和 JpaRepository getOne() 的区别