I have a project that uses Spring Boot JPA (spring-boot-starter-data-jpa dependency) which uses Hibernate as a JPA implementation.
I have my container auto configured (@EnableAutoConfiguration) and I use an EntityManager for CRUD operations.
Issue: I load my entities at startup via HQL queries using this EntityManager, but when I want to edit or delete any of them I get the following error
org.springframework.dao.InvalidDataAccessApiUsageException: Removing a detached instance com.phistory.data.model.car.Car#2; nested exception is java.lang.IllegalArgumentException: Removing a detached instance com.phistory.data.model.car.Car#2
org.springframework.dao.InvalidDataAccessApiUsageException: Entity not managed; nested exception is java.lang.IllegalArgumentException: Entity not managed
Libraries:
- spring-boot-starter-data-jpa 1.4.4.RELEASE (Hibernate 5.0.11.Final)
Main:
@SpringBootApplication
@EnableAutoConfiguration
@Slf4j
public class Main {
public static void main(String[] args) {
try {
SpringApplication.run(Main.class, args);
} catch (Exception e) {
log.error(e.toString(), e);
}
}
Database config (no beans explicitly declared, EntityManager gets automatically autowired):
@Configuration
@ComponentScan("com.phistory.data.dao")
@EntityScan("com.phistory.data.model")
@EnableTransactionManagement
@PersistenceUnit
public class SqlDatabaseConfig {
}
DAO
@Transactional
@Repository
public class SqlCarDAOImpl extends SqlDAOImpl<Car, Long> implements SqlCarDAO {
@Autowired
public SqlCarDAOImpl(EntityManager entityManager) {
super(entityManager);
}
@Override
public List<Car> getAll() {
return super.getEntityManager()
.createQuery("FROM Car AS car")
.getResultList();
}
}
Parent DAO
@Transactional
@Repository
@Slf4j
@NoArgsConstructor
public abstract class SqlDAOImpl<TYPE extends GenericEntity, IDENTIFIER> implements SqlDAO<TYPE, IDENTIFIER> {
@Getter
@PersistenceContext
private EntityManager entityManager;
public SqlDAOImpl(EntityManager entityManager) {
this.entityManager = entityManager;
}
public void saveOrEdit(TYPE entity) {
if (entity != null) {
if (entity.getId() == null) {
log.info("Saving new entity: " + entity.toString());
this.entityManager.persist(entity);
} else {
log.info("Editing entity: " + entity.toString());
this.entityManager.refresh(entity);
}
}
}
public void delete(TYPE entity) {
if (entity != null) {
log.info("Deleting entity: " + entity.toString());
this.entityManager.remove(entity);
}
}
public Session getCurrentSession() {
return this.entityManager.unwrap(Session.class);
}
}
Why are the entities I load not attached to the Session? Saving a new entity obviously works fine since the entity must not be managed at that point.
Thanks a lot Greetings