首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >@OneToMany为什么不能在Hibernate中使用继承

@OneToMany为什么不能在Hibernate中使用继承
EN

Stack Overflow用户
提问于 2008-09-01 15:21:01
回答 6查看 29.6K关注 0票数 11
代码语言:javascript
复制
@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“)中找不到这样的属性”。

我只找到了。我找不到艾曼纽尔·伯纳德的帖子来解释这背后的原因。

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

我想这意味着如果我有这两门课:

代码语言:javascript
复制
public class A {
    private int foo;
}

@Entity
public class B extens A {
}

然后字段foo将不会映射到B类,这是有意义的。但如果我有这样的东西

代码语言:javascript
复制
@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,并使用相同的表映射两个类。(事实上,这正是发生的事情,我刚刚又检查了一下)。我有一张桌子:

代码语言:javascript
复制
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构建的项目。它是JBoss4.0。)--有些东西+ hibernate已经存在了(您可以一起下载)。我把这个项目转移到JBoss4.2.2,发现有继承的"@OneToMany mappedBy“映射,它在旧的设置上运行得很好.)

EN

回答 6

Stack Overflow用户

回答已采纳

发布于 2008-09-10 05:06:10

我认为这是Hibernate团队做出的明智决定。他们可以减少自夸,并清楚地说明为什么是这样实现的,但这正是Emmanuel,Chris和Gavin的工作方式。:)

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

想象一下它将如何映射到数据库。您只有一个表继承,因此:

代码语言:javascript
复制
          _____________
          |__PROBLEMS__|          |__PEOPLE__|
          |id <PK>     |          |          |
          |person <FK> | -------->|          |
          |problemType |          |_________ |
          -------------- 

如果hibernate的problemType是相等的,那么hibernate将如何强制执行数据库,使只与People相关?这是一个很难解决的问题。所以,如果你想要这种关系,每个子类都必须在它自己的表中。这就是@MappedSuperclass所做的。

PS.:对不起这张难看的画:D

票数 8
EN

Stack Overflow用户

发布于 2014-09-29 00:44:00

在我的例子中,我想使用SINGLE_TABLE继承类型,所以使用@MappedSuperclass不是一个选项。

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

代码语言:javascript
复制
@OneToMany(mappedBy="person")
@Where(clause="DTYPE='UP'")
private List< UglyProblem > problems;
票数 9
EN

Stack Overflow用户

发布于 2008-09-02 07:56:52

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

在您的例子中,您可以定义以下内容:

代码语言:javascript
复制
public interface Problem {
    public Person getPerson();
}

public interface UglyProblem extends Problem {
}

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

代码语言:javascript
复制
@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编写代码,那么以后更改底层映射就更容易了(降低破坏兼容性的风险)。

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/38057

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档