java - 存在原始打字问题

标签 java jpa generics inheritance

我有一个继承问题,用代码而不是文本更容易解释问题,因此给出 Parent 的以下继承设计s:

@Entity
@Inheritance(strategy = InheritanceType.JOINED)
public class Parent<T extends Offspring> {

    @OneToMany(mappedBy = "parent", targetEntity = Offspring.class)
    private Set<T> offsprings;

    // Getters/Setters relevant for all sub types
}

@Entity
public class Cat extends Parent<Kitten> {

}

@Entity
public class Dog extends Parent<Puppy> {

}

还有Offspring :

@Entity
@Inheritance(strategy = InheritanceType.JOINED)
public class Offspring<T extends Parent> {
    @ManyToOne(targetEntity = Parent.class)
    @JoinColumn(name = "parent_id", referencedColumnName = "id")
    private T parent;

    // Getters/Setters relevant for all sub types
}

@Entity
public class Kitten extends Offspring<Cat> {

}

@Entity
public class Puppy extends Offspring<Dog> {

}

假设我想获取 parent 名单:List<Parent> parents = parentService.getAll();

父列表,因为它现在是原始类型,所以不理解 parents..get(0).getOffsprings()应该返回类型 Set<Offspring> 。相反,由于原始类型,它认为它返回 Set .

我可能想这样做,因为 Person可能有一个包含所有Parent的列表就像:

@Entity
public class Person {
    @OneToMany(mappedBy = 'person')
    private Set<Parent> parents;
}

我可能想要获得该人拥有的所有 parent 的所有后代:person.getParents().get(0).getOffsprings()但这会返回类型 Set因为它是原始类型。

显然我走错了路,所以:

目标是:

  • 能够拥有 Cat 的对象并且只能放 Kitten后代进入其集合。或者 Puppy 的对象并且只能是 可以设置Dog作为其父级。
  • 能够查询所有Parent s 并让它保持打字状态 那只是Offspring可以放入对象中。

对于如何完成此操作,我经历了许多不同的排列。例如,一种选择是 Cat对象来容纳其自己的容器 Kitten后代:

@Entity
@Inheritance(strategy = InheritanceType.JOINED)
public class Parent {
    @OneToMany(mappedBy = "parent")
    private Set<Offspring> offsprings;
}

@Entity
public class Cat extends Parent {

    private Set<Cat> offsprings;
}

但这不起作用,因为 Cat类无法覆盖父类的 getter/setter Parent 。以及导致 Hibernate 问题,因为它现在数据库表 Kitten有一个链接到Cat .

免责声明

我可能会遗漏一些明显的东西,或者以完全错误的方式处理这个问题,所以我愿意接受关于处理这个问题的最佳方法的建议。此外,我的继承策略可能会导致问题,因此欢迎所有建议,如果需要,我很乐意提供更多建议。

最佳答案

看起来您正在寻找的是 abstract类(和方法)。这些允许您指定行为并将实现留给其子类。我会做ParentOffspring abstract class es,然后继承它们,同时指定确切的返回类型:

public abstract class Parent {

    public abstract Set<? extends Offspring> getOffsprings();
}

public abstract class Offspring {

    public abstract Parent getParent();
}

public class Cat extends Parent {

    private Set<Kitten> offsprings;

    @Override
    public Set<Kitten> getOffsprings() {
        return offsprings;
    }
}

public class Kitten extends Offspring {

    private Cat parent;

    @Override
    public Cat getParent() {
        return parent;
    }
}

public class Dog extends Parent {

    private Set<Puppy> offsprings;

    @Override
    public Set<Puppy> getOffsprings() {
        return offsprings;
    }
}

public class Puppy extends Offspring {

    private Dog parent;

    @Override
    public Dog getParent() {
        return parent;
    }
}

Offspring类规定了一个返回 Parent 的方法,它的子类可以返回它的子类型,如 CatDog 。我相信它的名字叫Liskov substitution principle .

说到Animal ,它规定了一个返回 Set<? extends Offspring> 的方法,这意味着“扩展 Offspring 的特定单一类型”(与 Set<Offspring> 相反,这意味着“任何 Offspring ”,并且会给您一个编译错误)。这允许子类型返回 Set 他们的特定Offspring ,例如 Set<Kitten>Set<Puppy> .

现在,当你有 List<Parent> parents = parentService.getAll();每个Parent将返回 Set<? extends Offspring>通过parent.getOffsprings() .

关于java - 存在原始打字问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51963500/

相关文章:

Scala 泛型 < : and multiple traits

c# - 将泛型 IEnumerable<T> 转换为 IEnumerable<KeyValuePair> (C#)

java - Hibernate 搜索 NoSuchMethodError

java - 如何在 JEE 服务器 (Wildfly) 中的 JMS 临时队列上创建监听器?

Java Spring 启动 : How to find all rows with multiple Ids like findAllByAge(ArrayList<Long> ageList)?

sql - 在什么情况下 SELECT by PRIMARY KEY 会很慢?

java - Android正则表达式模式未封闭字符错误

java - 使用字符串数组查找引号

java - Hibernate @ManyToOne 引用了一个未知实体

.net - 不支持 C++/CLI 使用 Action<...,...> 和 Func<...>?