EclipseLink JPA继承没有鉴别器列

时间:2014-03-14 19:12:16

标签: java jpa eclipselink discriminator

我有一个Client和Affiliate类,继承自Person类。正在使用加入的继承策略类型 - 每个类型与父类共享主键。由于没有鉴别器列,我们选择使用DescriptorCustomizer and ClassExtractor。但它并没有真正理解它是如何工作的,而且,代码似乎没有编译。如果有人用代码片段给出一个很好的例子来理解,那就太好了。

1 个答案:

答案 0 :(得分:6)

根据mentioned documentation

  

如果要映射到现有数据库,并且表没有   一个鉴别器列你仍然可以使用。来定义继承   @ClassExtractor注释或<class-extractor>元素。班级   提取器采用实现ClassExtractor的类   接口。此类的实例用于确定类   用于数据库行的类型。类提取器必须定义一个   获取数据库extractClassFromRow()和的Record方法   Session

我们需要使用类提取器来定义用户定义的层次结构中的根实体:

@Entity
@Inheritance(strategy = InheritanceType.JOINED)
@ClassExtractor(PersonClassExtractor.class)
public abstract class Person {
    @Id @GeneratedValue(strategy = GenerationType.AUTO)
    private int id;
    private String name;
    private int age;
    // ...
}

请注意,我们不使用@Customizer注释,因为在JOINED继承策略的情况下不需要这样做:

  

如果类提取器与SINGLE_TABLE继承一起使用,则行   必须能够在查询中过滤类类型。这可以   通过设置onlyInstancesExpression()或   withAllSubclassesExpression()用于分支类。这些都可以设定   使用ExpressionDescriptorCustomizer个对象。

类提取器必须能够从数据库行确定并返回类类型。 一般来说,我们需要更换一个鉴别器列,即

  • 特定于给定实体类型的列名
  • 基于根实体的给定列的值的标准

假设层次结构中的每个继承实体类型都有一个具有唯一名称的列:

@Entity
public class Client extends Person {
    @Column(name = "CLIENT_SPECIFIC")
    private String clientSpecific;
    // ...
}

@Entity
public class Affiliate extends Person {
    @Column(name = "AFFILIATE_SPECIFIC")
    private float affiliateSpecific;
    // ...
}

然后类提取器可能如下所示:

public class PersonClassExtractor extends ClassExtractor {
    @Override
    public Class<?> extractClassFromRow(Record databaseRow, Session session) {
        if (databaseRow.containsKey("CLIENT_SPECIFIC")) {
            return Client.class;
        } else if (databaseRow.containsKey("AFFILIATE_SPECIFIC")) {
            return Affiliate.class;
        } else {
            return Person.class; // this should never happen
        }
    }
}

  • 检索客户和关联公司列表
List<Person> polymorphicResults = em.createQuery("SELECT p FROM Person p")
                                    .getResultList();
  • 分别检索关联公司或客户列表
List<Affiliate> concreteResults = em.createQuery("SELECT a FROM Affiliate a")
                                    .getResultList();

List<Client> concreteResults = em.createQuery("SELECT c FROM Client c")
                                 .getResultList();