Reputation: 1265
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
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
Reputation: 81
Try to use merge before refresing.
public void refresh(T entity) {
this.entityManager.refresh(this.entityManager.merge(entity));
}
Upvotes: 6
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
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