Geo*_*uba 6 java orm inheritance hibernate
@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;
}
Run Code Online (Sandbox Code Playgroud)
我觉得很清楚我想要做什么.我希望@ManyToOne人能够被UglyProblem类继承.但是会有例外情况说:"UglyProblem类中没有找到这样的属性(mappedBy ="person")".
我发现的就是这个.我无法找到Emmanuel Bernard解释其背后原因的帖子.
不幸的是,根据Hibernate文档"忽略了未映射为@MappedSuperclass的超类属性".
嗯,我认为这意味着如果我有这两个类:
public class A {
private int foo;
}
@Entity
public class B extens A {
}
Run Code Online (Sandbox Code Playgroud)
然后字段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;
}
}
Run Code Online (Sandbox Code Playgroud)
我希望UglyProblem类具有fileds id,name并且使用相同的表来映射这两个类.(事实上,这正是发生的事情,我刚刚再次检查过).我有这张桌子:
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;
Run Code Online (Sandbox Code Playgroud)
回到我的问题:
我希望@ManyToOne人能够被UglyProblem类继承.
我希望这是因为所有其他映射字段都是继承的,我没有看到任何理由为ManyToOne关系设置此异常.
是的,我看到了.事实上,我在我的案例中使用了只读解决方案.但我的问题是"为什么......":).我知道hibernate团队成员有一个解释.我无法找到它,这就是我问的原因.
我想找出这个设计决定的动机.
(如果你对我如何面对这个问题感兴趣:我继承了一个使用hibernate 3构建的项目.它是Jboss 4.0.something + hibernate已经存在(你将它们全部下载).我正在将这个项目移动到Jboss 4.2. 2,我发现有"@OneToMany mappedBy"的继承映射,它在旧设置上工作正常...)
小智 7
在我的情况下,我想使用SINGLE_TABLE继承类型,因此使用@MappedSuperclass不是一个选项.
什么有用,虽然不是很干净,但是将Hibernate专有的@Where子句添加到@OneToMany关联以强制查询中的类型:
@OneToMany(mappedBy="person")
@Where(clause="DTYPE='UP'")
private List< UglyProblem > problems;
Run Code Online (Sandbox Code Playgroud)
不幸的是,根据Hibernate 文档, “未映射为@MappedSuperclass的超类的属性将被忽略。” 我也反对这一点。我的解决方案是通过接口而不是实体bean本身来表示所需的继承。
您可以定义以下内容:
public interface Problem {
public Person getPerson();
}
public interface UglyProblem extends Problem {
}
Run Code Online (Sandbox Code Playgroud)
然后使用抽象超类和两个实体子类实现这些接口:
@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 {
}
Run Code Online (Sandbox Code Playgroud)
另外一个好处是,如果您使用接口而不是使用实现这些接口的实际实体Bean进行编码,则以后可以更轻松地更改基础映射(减少破坏兼容性的风险)。
我认为这是 Hibernate 团队做出的明智决定。他们可以不那么傲慢,并明确说明为什么以这种方式实施,但这就是 Emmanuel、Chris 和 Gavin 的工作方式。:)
让我们试着理解这个问题。我认为你的概念是“撒谎”。首先,您说许多Problem都与People相关联。但是,然后您说一个Person有许多UglyProblem(并且与其他Problem s无关)。那个设计有问题。
想象一下它将如何映射到数据库。您只有一个表继承,因此:
_____________
|__PROBLEMS__| |__PEOPLE__|
|id <PK> | | |
|person <FK> | -------->| |
|problemType | |_________ |
--------------
Run Code Online (Sandbox Code Playgroud)
如果问题类型等于 UP,hibernate 将如何强制数据库使问题仅与人员相关?这是一个非常难以解决的问题。所以,如果你想要这种关系,每个子类都必须在它自己的表中。这就是它的作用。@MappedSuperclass
PS。:对不起,丑陋的图画:D