0

I have a generic JPA repository implementation dealing with many type of entities as follows:

@Component
@Transactional(transactionManager = "ubldbTransactionManager")
public class CatalogueRepositoryImpl {
...

    @PersistenceContext(unitName = eu.nimble.utility.Configuration.UBL_PERSISTENCE_UNIT_NAME)
    private EntityManager em;

    public <T> void deleteEntity(T entity) {
        if(!em.contains(entity)) {
            entity = em.merge(entity);
        }
        em.remove(entity);
    }

    public <T> List<T> getEntities(String queryStr) {
        Query query = em.createQuery(queryStr);
        List<T> result = query.getResultList();
        return result;
    }
...
}

At some point I realized that some of the entities have not been deleted. Then, I found out that some managed entities cause cancellation of the removal, as described at: https://stackoverflow.com/a/16901857/502059

Since the method is generic, it included various types of entities inside. As a work around, I wanted to get rid of the entities causing cancellation of deletion and I added em.flush() and em.clear() at the beginning of the deleteEntity method. Although this worked, I feel that this is a dirty workaround.

So, I'm asking some best practices for such a case. For example, would creating a new EntityManager in deleteEntity be an alternative? I didn't want this since I wanted Spring to handle managing the scope of EntityManagers and transactions.

One last point about Spring-managed EntityManager: I also wonder whether the em in the example managed by Spring is an application-scope one? If so, wouldn't it keep all the retrieved entities and expand continuously?

Vlad Mihalcea
  • 142,745
  • 71
  • 566
  • 911
suat
  • 4,239
  • 3
  • 28
  • 51
  • Why are you maintaining this by hand instead of using a Spring Data repository? – chrylis -cautiouslyoptimistic- Nov 28 '18 at 21:41
  • Since there are too many entity types, I didn't want to create a separate repository for each entity type. Also, specific to the entity type of interest included in the removal operation, I also tried to create a `JpaRepository` but the result was the same. So, I thought the same EntityManager instance was being used. I wonder if I come across such issues if I created individual repositories. – suat Nov 28 '18 at 21:46

1 Answers1

1

If you're using Hibernate, you don't need to do the merge prior to deleting the entity. That's only a JPA requirement, but Hibernate is more lenient in that regard.

You could also do something like:

entity = em.getReference(entity.getClass(), entity.getId());
em.remove(entity);

If that does not work, it could be because you are not cascading the REMOVE operation to child associations.

You can make the T argument extend an Identifiable interface which defines the getId method and have your entities implement this interface so that your method is more generic.

Vlad Mihalcea
  • 142,745
  • 71
  • 566
  • 911
  • thanks a lot for your response. Yes, I use Hibernate. However, it didn't work although all the child associations (B->C1, B->C2, ...) have `cascade = {CascadeType.ALL}`. However, I guess the reason is that there is a **managed parent object A, (A->B)** in the **same entity manager**. Because I still see `un-scheduling entity deletion` logs. – suat Nov 29 '18 at 08:23
  • Actually, there are no bidirectional associations. Associations are in the form of `A-> B` and `B->C`. All associations have `CascadeType.ALL`. `B` is the entity that I'm trying to delete and there are `A` instances in the entity manager referring to the B instance that I'm trying to delete. So, I think I can either `nullify` A's references to B and `update` `A`. Since the entities have also `orphanRemoval=true` associations, `B` would be deleted. However, do you think performing `flush` and `clear` before `remove` make sense or is a valid pattern? – suat Nov 29 '18 at 10:17
  • Try to replicate it with [this test case template](http://in.relation.to/2016/01/14/hibernate-jpa-test-case-template/) so I can see the issue in practice. – Vlad Mihalcea Nov 29 '18 at 10:44