10
@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
public class Problem {
    @ManyToOne
    private Person person;
}

@Entity
@DiscriminatorValue("UP")
public class UglyProblem extends Problem {}

@Entity
public class Person {
    @OneToMany(mappedBy="person")
    private List< UglyProblem > problems;
}

我认为很清楚我要做什么。我希望 @ManyToOne 人被 UglyProblem 类继承。但是会有一个例外说:“在 UglyProblem 类中没有找到这样的属性 (mappedBy="person")”。

我发现的只有这个。我找不到 Emmanuel Bernard 的帖子,解释了这背后的原因。


不幸的是,根据 Hibernate 文档“未映射为 @MappedSuperclass 的超类的属性将被忽略。”

那么我认为这意味着如果我有这两个类:

public class A {
    private int foo;
}

@Entity
public class B extens A {
}

那么字段foo将不会映射到 B 类。这是有道理的。但如果我有这样的事情:

@Entity
public class Problem {

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;

private String name;

public Long getId() {
    return id;
}

public void setId(Long id) {
    this.id = id;
}

public String getName() {
    return name;
}

public void setName(String name) {
    this.name = name;
}
}

@Entity
public class UglyProblem extends Problem {

private int levelOfUgliness;

public int getLevelOfUgliness() {
    return levelOfUgliness;
}

public void setLevelOfUgliness(int levelOfUgliness) {
    this.levelOfUgliness = levelOfUgliness;
}
}

我希望 UglyProblem 类有文件idname并且两个类都使用同一个表进行映射。(事实上​​,这正是发生的事情,我刚刚再次检查)。我有这张桌子:

CREATE TABLE "problem" (
    "DTYPE" varchar(31) NOT NULL,
    "id" bigint(20) NOT NULL auto_increment,
    "name" varchar(255) default NULL,
    "levelOfUgliness" int(11) default NULL,
    PRIMARY KEY  ("id")
) AUTO_INCREMENT=2;

回到我的问题:

我希望 @ManyToOne 人被 UglyProblem 类继承。

我希望这是因为所有其他映射字段都是继承的,并且我认为没有任何理由为 ManyToOne 关系设置此例外。


是的,我看到了。事实上,我在我的案例中使用了只读解决方案。但我的问题是“为什么……” :)。我知道hibernate团队的成员给出了解释。我找不到它,这就是我问的原因。

我想找出这个设计决策的动机。

(如果你对我如何面对这个问题感兴趣:我继承了一个使用 hibernate 3 构建的项目。它是 Jboss 4.0。一些东西 + hibernate 已经存在(你可以一起下载)。我正在将此项目移动到 Jboss 4.2。 2,我发现有“@OneToMany mappedBy”的继承映射,它在旧设置上运行良好......)

4

6 回答 6

8

在我的情况下,我想使用 SINGLE_TABLE 继承类型,所以使用 @MappedSuperclass 不是一个选项。

什么工作,虽然不是很干净,是将 Hibernate 专有的@Where子句添加到 @OneToMany 关联以强制查询中的类型:

@OneToMany(mappedBy="person")
@Where(clause="DTYPE='UP'")
private List< UglyProblem > problems;
于 2014-09-29T00:44:00.207 回答
6

我认为这是 Hibernate 团队做出的明智决定。他们可以不那么傲慢,并清楚说明为什么要以这种方式实施,但这正是 Emmanuel、Chris 和 Gavin 的工作方式。:)

让我们试着理解这个问题。我认为您的概念是“撒谎”。首先,您说许多问题People相关联。但是,然后您说一个Person有许多UglyProblem(并且与其他问题无关)。那个设计有问题。

想象一下它将如何映射到数据库。你有一个单一的表继承,所以:

          _____________
          |__PROBLEMS__|          |__PEOPLE__|
          |id <PK>     |          |          |
          |person <FK> | -------->|          |
          |problemType |          |_________ |
          -------------- 

如果问题类型等于 UP ,休眠将如何强制数据库使问题仅与人相关?这是一个非常难以解决的问题。所以,如果你想要这种关系,每个子类都必须在它自己的表中。就是这样。@MappedSuperclass

PS.:对不起,丑陋的图画:D

于 2008-09-10T05:06:10.240 回答
5

不幸的是,根据 Hibernate文档“未映射为 @MappedSuperclass 的超类的属性将被忽略。” 我也遇到了这个。我的解决方案是通过接口而不是实体 bean 本身来表示所需的继承。

在您的情况下,您可以定义以下内容:

public interface Problem {
    public Person getPerson();
}

public interface UglyProblem extends Problem {
}

然后使用一个抽象超类和两个实体子类来实现这些接口:

@MappedSuperclass
public abstract class AbstractProblemImpl implements Problem {
    @ManyToOne
    private Person person;

    public Person getPerson() {
        return person;
    }
}

@Entity
public class ProblemImpl extends AbstractProblemImpl implements Problem {
}

@Entity
public class UglyProblemImpl extends AbstractProblemImpl implements UglyProblem {
}

作为一个额外的好处,如果您使用接口而不是实现这些接口的实际实体 bean 进行编码,那么以后更改底层映射会更容易(破坏兼容性的风险更小)。

于 2008-09-02T07:56:52.333 回答
1

我认为您需要使用@MappedSuperclass而不是@Entity来注释您的问题超类。

于 2008-09-01T16:09:47.947 回答
0

我想出了如何解决 OneToMany mappedBy 问题。

在原始帖子的派生类 UglyProblem 中。回调方法需要在派生类而不是父类中。

@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@ForceDiscriminator
public class Problem {

}

@Entity
@DiscriminatorValue("UP")
public class UglyProblem extends Problem {
    @ManyToOne
    private Person person;
}

@Entity
public class Person {
    @OneToMany(mappedBy="person")
    private List< UglyProblem > problems;
}

至少找到了使用 Hibernate 的秘诀。 http://docs.jboss.org/hibernate/stable/annotations/api/org/hibernate/annotations/ForceDiscriminator.html @ForceDiscriminator 使 @OneToMany 尊重鉴别器

需要休眠注释。

于 2009-12-17T18:28:11.677 回答
-2

在我看来,@JoinColumn 至少应该提供一个选项来将 @DiscriminatorColumn = @DiscriminatorValue 应用于 SQL“where”子句,尽管我更希望这种行为是默认行为。

我很惊讶在 2020 年这仍然是一个问题。由于这种对象设计模式并不罕见,我认为 JPA 还没有在规范中涵盖这个简单的特性是一种耻辱,因此仍然迫使我们寻找丑陋的解决方法。

为什么一定要这么难?这只是一个额外的 where 子句,是的,我确实为 @JoinColumn、@DiscriminatorColumn 组合准备了一个数据库索引。

.i.. JPA

引入您自己的自定义注释并编写生成本机查询的代码。这将是一个很好的锻炼。

于 2020-06-16T12:03:37.020 回答