Bilal Shah
Bilal Shah

Reputation: 1265

Spring data Jpa Entity not managed Exception when calling refresh

I have a db code jar which I use in different application for accessing db. I am using spring data jpa. I need to call refresh to check for change in row in db from some other application. Here How I implement it. My StudentRepository interface:

public interface StudentRepository extends JpaRepository<StudentEntity, Integer>, StudentRepositoryCustom {}

My StudentRespositoryCustom interface

public interface StudentRepositoryCustom {
    void detach(StudentEntity studentEntity);
    void refresh(StudentEntity studentEntity);}

My StudentRepositoryCustomImpl class

public class StudentRepositoryImpl implements StudentRepositoryCustom {

@PersistenceContext
EntityManager entityManager;

@Override
@Transactional
public void detach(StudentEntity studentEntity) {
    entityManager.detach(studentEntity);
}

@Override
@Transactional
public void refresh(StudentEntity studentEntity) {
    entityManager.refresh(studentEntity);
}}

My Test

@Test
public void refreshTest(){
    StudentEntity studentEntity = studentRepository.findOne(6);
    studentRepository.refresh(studentEntity);
}

But it throws this exception:

org.springframework.dao.InvalidDataAccessApiUsageException: Entity not managed; nested exception is java.lang.IllegalArgumentException: Entity not managed

at org.springframework.orm.jpa.EntityManagerFactoryUtils.convertJpaAccessExceptionIfPossible(EntityManagerFactoryUtils.java:384)
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.translateExceptionIfPossible(AbstractEntityManagerFactoryBean.java:492)
at org.springframework.dao.support.ChainedPersistenceExceptionTranslator.translateExceptionIfPossible(ChainedPersistenceExceptionTranslator.java:59)

This line in hibernate-core-5.2.1.final SessionImpl class return null

EntityEntry entry = persistenceContext.getEntry( object );

It should return entity I think.

My persistence.xml file is

<persistence-unit name="testPersitanceUnit" transaction-type="RESOURCE_LOCAL">
    <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
    <class>com.sample.dao.gen.StudentEntity</class>
    <properties>
        <property name="hibernate.archive.autodetection" value="class"/>
        <property name="hibernate.show_sql" value="true"/>
        <property name="hibernate.format_sql" value="true"/>
        <property name="hbm2ddl.auto" value="update"/>
        <property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5InnoDBDialect" />
        <property name="hibernate.enable_lazy_load_no_trans" value="true" />
    </properties>
</persistence-unit>

My spring db config file is

 <jpa:repositories base-package="com.sample.dao.repos"
                  entity-manager-factory-ref="entityManagerFactory" transaction-manager-ref="transactionManager"/>

<!-- Enable the component scan (auto wiring etc) for the following package -->
<context:component-scan base-package="com.sample.dao" />

<!-- Make sure the following is specified to enable transaction  -->
<tx:annotation-driven />
<bean class="org.springframework.orm.jpa.JpaTransactionManager" id="transactionManager">
    <property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>

<!--  This defines the entity manager factory with some custom properties -->
<bean id='entityManagerFactory' primary="true" class='org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean'>
    <property name="persistenceUnitName" value="testPersitanceUnit"/>
    <property name='dataSource' ref='dataSource' />
    <property name="packagesToScan" value="com.sample.dao" />
enter code here

Upvotes: 8

Views: 16085

Answers (4)

Ranjithkumar
Ranjithkumar

Reputation: 18406

I fixed same issue with different approach

Initially my code like this

    myRepository.saveAndFlush(myEntity);
    myRepository.refresh(myEntity); 

It seems correct.

But problem is updated entity returned by saveAndFlush((), we should refresh the updated entity.

After I update the "myEntity" returned by saveAndFlush(), error was fixed

    myEntity = myRepository.saveAndFlush(myEntity);//update the latest before refreshing 
    myRepository.refresh(myEntity); 

Upvotes: 2

Aleksey Kovalyov
Aleksey Kovalyov

Reputation: 81

Try to use merge before refresing.

public void refresh(T entity) {
        this.entityManager.refresh(this.entityManager.merge(entity));

  }

Upvotes: 6

Bilal Shah
Bilal Shah

Reputation: 1265

Actually it was a query issue. The query was producing inner join and hence return empty list so it was throwing exception. I changed the mapping so that it can produce outer join and it than return a row and it was successfull.

Upvotes: -2

Jeff Wang
Jeff Wang

Reputation: 1867

try

public StudentEntity refresh(StudentEntity studentEntity) {
    StudentEntity managedEntity = entityManager.find(StudentEntity.class, studentEntity.getId());
    entityManager.refresh(managedEntity);
    return managedEntity;
}}

The reason you are having the problem is that in your test, your studentEntity was passed outside of the transaction (findOne), and therefore no longer managed. When it gets passed into a new transaction (refresh) it is not managed, and so throws this error.

Alternatively, if the original refresh is desired behavior, you can wrap your entire test in a transaction, that should maintain management of your test object.

Upvotes: 9

Related Questions