4

我有一个场景如下:

@Entity
@Table(name = "ANIMAL")
@Inheritance(strategy = InheritanceType.JOINED)

public class Animal implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "S_ANIMAL")
    @SequenceGenerator(name = "S_ANIMAL", sequenceName = "S_ANIMAL", allocationSize = 1)
    public int getNumero() {
        return numero;
    }

    public void setNumero(int numero) {
        this.numero = numero;
    }
        .
        .
        .
}

并作为子类:

@Entity
@Table(name = "DOG")
public class Dog extends Animal {

    private static final long serialVersionUID = -7341592543130659641L;
        .
        .
        .
}

我有一个这样的 JPA Select 语句:

SELECT a FROM Animal a;

我正在使用休眠 3.3.1

正如我所看到的,框架检索使用左外连接的实例AnimalDog使用左外连接的实例。

有没有办法只选择“部分” Animal?我的意思是,前一个Select会得到所有的Animals,那些只有Animals 但不是Dogs 和那些是Dogs。

我想要它们,但在Dogs 的情况下,我只想检索它们的“动物部分”。

我找到了,@org.hibernate.annotations.Entity(polymorphism = PolymorphismType.EXPLICIT) 但是我可以看到这仅在 Animal 不是@Entity.

非常感谢。

4

2 回答 2

3

简短回答:您描述的行为符合 JPA 标准。没有 JPA 标准方法来限制 JPA 提供者只检索超类。

提供者可以选择查询实现逻辑来实现功能、一致性和性能。只要它尊重您的实体注释并在查询中返回请求的信息,一切都很好。将 Dog 的外部连接视为您不应该关心的私有实现细节。提供者已对外部连接进行编码以提高性能和一致性。

考虑:

  • JPA 被定义为处理 java 对象实体而不是表
  • 实体层次结构的根 Animal 不是抽象的,因此您可以创建一个实例并将其持久化。
  • 您有 Animal @DecriminatorColumn 和 @DescriminatorType 的默认值 - 因此 Animal 表将添加一个带有名称“DTYPE”的鉴别器列并键入“some String type”。@DecriminatorValue 有一个默认值 - 将等于实体名称:Animal。所以 Animal.DTYPE column = "Animal" 当你创建这个实体时。
  • 实体狗有一个超类动物。默认值也用于其@DecriminatorValue - Dog。所以 Animal.DTYPE column = "Dog" 当你创建这个实体时。
  • Java 类限制确保只要存在 Dog 对象,相应的 Animal 超类对象也存在。
  • 通常,当您将实体 Animal 加载到 JPA 持久性上下文中时,@DecriminatorValue(存储在 DTYPE 列中的值)=“Dog”,那么将 Dog 对象加载到 PC 中以保持一致性非常有用。即使它不是 JPA 标准所要求的。
  • 继承关系不能指定为 EAGER 或 LAZY(如基本类型字段或实体关系字段)。如果您需要读取/更新狗属性并且未加载 Dog 类,您会怎么做?运行一个单独的查询来重新加载它?这会极大地损害一致性和性能。
  • 性能的主要关注点是发送到数据库的单独 SQL 命令的总数。
    就所用时间而言:使用动物表的查询仅比使用动物外连接到狗的查询稍快(10 微秒???),但比两个单独的查询(一个用于动物,一个用于狗)快得多
于 2012-11-02T07:09:41.870 回答
0

实际上,有一种方法可以只获取超类:您只需要使用来自 JPA 的本机查询。就我而言,我使用的是 JPA 存储库。因此,它会是这样的:

@Query(value = "SELECT * FROM animal", nativeQuery = true)
List<Resource> findAllAnimal();

将 nativeQuery 标记为 true 允许在数据库上运行本机 SQL。

如果您使用的是实体管理器,请查看:https ://www.thoughts-on-java.org/jpa-native-queries/

于 2018-05-09T20:33:13.767 回答