我有一个通用的JPA存储库实现,可以处理多种类型的实体,如下所示:
@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;
}
...
}
在某个时候,我意识到某些实体尚未删除。然后,我发现某些managed
实体导致取消删除,如https://stackoverflow.com/a/16901857/502059
由于该方法是通用的,因此它内部包含各种类型的实体。作为一种变通方法,我想摆脱导致删除取消的实体,并在em.flush()
方法的开头添加了em.clear()
和deleteEntity
。尽管这可行,但我认为这是一个肮脏的解决方法。
因此,我想问这种情况下的一些最佳做法。例如,是否可以在EntityManager
中创建新的deleteEntity
?我不希望这样,因为我希望Spring处理EntityManagers
和transactions
的范围的管理。
关于Spring管理的EntityManager的最后一点 :我还想知道Spring管理的示例中的em
是否是应用程序范围的?如果是这样,它是否不保留所有检索到的实体并不断扩展?
答案 0 :(得分:1)
如果您使用的是Hibernate,则无需在删除实体之前执行merge
。这只是一个JPA要求,但是Hibernate在这方面更宽容。
您还可以执行以下操作:
entity = em.getReference(entity.getClass(), entity.getId());
em.remove(entity);
如果这不起作用,那可能是因为您没有将REMOVE操作级联到子关联。
您可以使T
参数扩展一个Identifiable
接口,该接口定义了getId
方法,并让您的实体实现此接口,以便您的方法更通用。