【问题标题】:Overriding EclipseLink EntityManager覆盖 EclipseLink EntityManager
【发布时间】:2014-04-13 20:04:01
【问题描述】:

有没有办法覆盖EclipseLink提供的EntityManager? 我想覆盖 EclipseLink's EntityManager.remove() 方法 - 我不想要物理移除(只有逻辑)。 很容易扩展适当的EntityManager

public class MyEntityManager extends org.eclipse.persistence.internal.jpa.EntityManagerImpl {

    public MyEntityManager(String sessionName) {
        super(sessionName);
    }

    public void remove(Object entity) {
        AbstractEntity en = (AbstractEntity)entity;
        en.setAuditRD(33333);
        this.merge(en);
    }
}

但是如何将其传递到 EclipseLink 的工厂以创建 MyEntityManager 而不是 org.eclipse.persistence.internal.jpa.EntityManagerImpl?也许有什么参数,我可以在persistence.xml文件中传递?

【问题讨论】:

    标签: java jpa eclipselink overriding


    【解决方案1】:

    persistence.xml 类中,provider 元素决定了这一点。只需将您的提供者实现放在那里(不是EntityManager)。摘自 JPA 规范:

    8.2.1.4 提供者

    provider 元素指定持久性提供者的 javax.persistence.spi.PersistenceProvider 的名称 班级。提供者元素是可选的,但应在以下情况下指定 应用程序依赖于特定的持久性提供程序 正在使用。

    文件示例:

    <persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
       <persistence-unit name="myapp">
          <provider>org.mydomain.ejb.MyPersistenceProvider</provider>
          <jta-data-source>java:/DefaultDS</jta-data-source>
       </persistence-unit>
    </persistence> 
    

    【讨论】:

    • 不幸的是,这是最好的解决方案。不幸的是,因为实现持久化提供者等于编写数百行代码。
    【解决方案2】:

    我认为覆盖实体管理器的默认行为是不合适的。如果您需要实际删除一个实体,那将是不可能的。

    最好有一些封装这些方法的辅助包装类,而不是直接访问实体管理器然后根据需要委托请求。

    下面是伪代码。

    /** Use this wrapper class instead of EntityManager*/
    class DBManager {
    
      /** Implementing required methods*/
      remove(E e){
       em.remove(e); //-- Removing entity from DB
      }
    
      /** Give any appropriate method name to use application wide
         and implement custom logic, discarding entity logically */
      markInActive(E e){
        AbstractEntity en = (AbstractEntity)e;
        en.setAuditRD(33333);
        em.merge(en);
       } 
    }
    

    【讨论】:

    • 你是对的(顺便说一句,我使用EJB),但问题与管理JPA 关系有关。假设我有一个EntityA,它的@OneToMany 映射到EntityB——这意味着EntityA 包含EntityB 的列表。现在,当我从这个列表中删除一些EntityB 并调用EntityManager.persist(entityA) 时,我想从逻辑上而不是物理上删除EntityB。不幸的是 JPA 调用 EntityManager 并将其物理删除。办公室。我可以遍历列表并分别更新每个元素,但是为什么 JPA 应该允许这样做呢?
    【解决方案3】:

    EcliseLink 支持软增量,无需覆盖 EntityManager。有关详细信息,请参阅http://wiki.eclipse.org/EclipseLink/Examples/JPA/SoftDelete。这允许您更改 EclipseLink 使用的删除查询,以便更改字段值而不是删除。您可以添加@AdditionalCriteria 以防止通过查询读入已删除的记录,从而使它们也显示为已删除。

    否则,除非您确定永远不会使用级联或私有所有权,否则您无法仅仅覆盖 EclipseLink EntityManagerImpl 上的 remove 方法。 remove 方法将工作委托给内部方法,对每个映射都有更多的了解,因此如果使用任何级联选项,您还需要覆盖或拦截内部调用。如果您不打算使用级联选项,我将创建您自己的一组持久性提供程序类和一个使用这些类的新持久性单元。然后,您的提供者类将查找第一个持久性单元并将其委托给它 - 类似于大多数容器如何使用代理类来注入工厂和 EntityManagers。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-03-31
      • 1970-01-01
      • 2012-06-03
      • 2010-12-17
      • 1970-01-01
      • 2014-09-30
      • 2011-03-15
      相关资源
      最近更新 更多