简体   繁体   English

Spring Data JPA(Hibernate):如何仅使用抽象超类中的字段来检索具体实体?

[英]Spring Data JPA(Hibernate): How do I retrieve a concrete entity using only a field in its abstract superclass?

Consider the following hierarchy, where entities WidgetA and WidgetB extend an abstract Widget superclass: 考虑以下层次结构,其中实体WidgetAWidgetB扩展了抽象Widget超类:

@Entity
@Inheritance(strategy = InheritanceType.JOINED)
public abstract class Widget implements Serializable  {

    @Column(name="serialNumber", length=64, nullable=false, unique=true)
    private String serialNumber;
    ...

and

@Entity
public class WidgetA extends Widget implements Serializable  {
...

and

@Entity
public class WidgetB extends Widget implements Serializable  {
...

I need to search for Widgets by serialNumber , but I don't know the concrete type of the Widget I'm searching for at runtime. 我需要通过serialNumber搜索Widget,但是我不知道我在运行时要搜索的Widget的具体类型。 What is the correct way to search for widgets by serialNumber such that if the serialNumber is that of a WidgetA , then an instance of WidgetA gets returned, and so on? 通过serialNumber搜索小部件的正确方法是什么,以便如果serialNumberWidgetA ,则返回WidgetA的实例,依此类推?

I am trying to use a findyBySerialNumber() in the Widget DAO, and I'm getting an error telling me I can't instantiate an abstract class, which makes sense, but I thought the persistence provider would know how to look in the concrete child entity tables and return the correct instance. 我正在尝试在Widget DAO中使用findyBySerialNumber() ,但遇到一个错误消息,告诉我我无法实例化一个抽象类,这很有意义,但是我认为持久性提供程序会知道如何看待具体内容。子实体表并返回正确的实例。 Can I make it do this? 我可以做到吗?

I am using "Spring Data JPA", so the Widget DAO is really simple: 我正在使用“ Spring Data JPA”,因此Widget DAO非常简单:

public interface WidgetDAO extends JpaRepository<Widget, Long> {
    public Widget findBySerialNumber(String serialNumber);
}

It seems you didn't specify a discriminator explicitly for your widget hierarchy. 似乎您没有为窗口小部件层次结构明确指定区分符。 I think you can try to define it explicitly because Spring Data will manipulate bytecode to generate the queries, and so I suspect SpringData need to have those values explicitely defined. 我认为您可以尝试明确定义它,因为Spring Data会操纵字节码来生成查询,因此我怀疑SpringData需要明确定义那些值。

Additionally in subclasses you need to indicate the discriminator value for each subclass. 另外,在子类中,您需要指示每个子类的鉴别值。

@Entity
@Inheritance(strategy = InheritanceType.JOINED)
@DiscriminatorColumn(name="WIDGET_TYPE")
public abstract class Widget implements Serializable  {

    @Column(name="serialNumber", length=64, nullable=false, unique=true)
    private String serialNumber;
    ...

- --

@Entity
@DiscriminatorValue("A")
public class WidgetA extends Widget implements Serializable  {
...

- --

@Entity
@DiscriminatorValue("B")
public class WidgetB extends Widget implements Serializable  {
...

Your objects and annotations look fine to me. 您的对象和注释对我来说很好。 I was able to take them, save a widget to a database, and fetch it out without a problem. 我能够接管它们,将小部件保存到数据库中,然后毫无问题地将其取出。

I think the the problem is in your data. 我认为问题出在您的数据中。 Hibernate is probably finding a row in the Widget table that does not have a corresponding row in any of the sub class tables, and is therefore trying to create an instance of the superclass, and failing. Hibernate可能正在Widget表中找到一行,而在任何子类表中都没有对应的行,因此尝试创建超类的实例并失败了。

With InheritanceType.JOINED , you can either specify a discriminator , or let it do it for you (I believe by checking whether a row with that ID exists in the subclass table). 使用InheritanceType.JOINED ,您可以指定一个标识符 ,也可以让它为您完成(我相信通过检查子类表中是否存在具有该ID的行)。 But either way, you have to check your data to make sure there's not an entry in the super class table without a matching subclass row. 但是无论哪种方式,您都必须检查数据,以确保超类表中没有没有匹配的子类行的条目。

As a rule, I support @ben75's recommendation that you do explicitly specify @Discriminator for class hierarchies. 通常,我支持@ ben75的建议,即您确实为类层次结构明确指定@Discriminator It's better to have control over your discriminator values, so that later code changes don't alter the values in unexpected ways. 最好控制您的标识符值,以便以后的代码更改不会以意外的方式更改值。

Hibernate supports that query just fine, and will happily return an instance of the correct subclass. Hibernate很好地支持该查询,并将愉快地返回正确子类的实例。 Without knowing what it is in the Spring Data implementation that is trying to make an instance of Widget, you should be able to just declare the query and have it run it directly, rather than using the parser. 在不知道试图创建Widget实例的Spring Data实现中是什么的情况下,您应该只能声明查询并直接运行查询,而不是使用解析器。

public interface WidgetDAO extends JpaRepository<Widget, Long> {

    @Query("select w from Widget w where w.serialNumer = ?1")
    public Widget findBySerialNumber(String serialNumber);
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何只修改spring数据jpa中的实体的一部分? - How do I modify only part of an entity in spring data jpa? Spring Data JPA + Hibernate:如何使用抽象超类上的存储库进行对象检索? - Spring Data JPA + Hibernate: How do I use a repository on abstract super class for object retrieval? 如何使用 spring-data-jpa 更新实体? - How do I update an entity using spring-data-jpa? 如何使用 Spring JPA DATA 仅获取特定的子实体及其具有特定值的父实体 - How to fetch only the specific child entity along with its Parent entities with specific value using Spring JPA DATA 如何使用spring-boot,spring-data-jpa和hibernate获得“无级联”的行为? - How do I get “no cascading”-behaviour using spring-boot, spring-data-jpa and hibernate? 如何使用Spring Data JPA更新实体中的集合字段? - How to update a collection field in entity using Spring Data JPA? Hibernate:如何将子类链接到其超类? - Hibernate: How do I link a subclass to its superclass? 如何使用 Spring data JPA 和 Hibernate 添加复合外键? - How do I add composite foreign key using Spring data JPA and Hibernate? 如何使用子实体检索父实体-Spring数据JPA - How to retrieve parent entity using child entity-Spring data JPA 如何在 Spring JPA/Hibernate 中使用 JoinTable 仅通过 ID 设置引用父实体的子实体 - How to set up a child entity referencing parent by only ID using a JoinTable in Spring JPA/Hibernate
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM