Java 为什么在使用@JoinTable时忽略@DiscriminatorColumn?
假设我有以下表格:Java 为什么在使用@JoinTable时忽略@DiscriminatorColumn?,java,hibernate,jpa,jakarta-ee,discriminator,Java,Hibernate,Jpa,Jakarta Ee,Discriminator,假设我有以下表格: ______________________ | LAWSUIT | |______________________| | ID | | TITLE | |______________________| \ \ \
______________________
| LAWSUIT |
|______________________|
| ID |
| TITLE |
|______________________|
\
\
\
______________________
| PERSONS_IN_THE_CASE |
|______________________|
| ID_LAWSUIT |
| ID_PERSON |
|______________________|
/
/
/
______________________
| PERSON |
|______________________|
| ID |
| NAME |
| TYPE | TYPE values = "Plantiff, Defendant, Lawyer, Judge, ..."
|______________________|
(我知道规范化数据库可以为每个人类型创建一个表,但让我们坚持实际结构)
我用JPA(2.0)对不同的人进行了如下分类:
@实体
@表(name=“PERSON”)
@继承(策略=InheritanceType.SINGLE_表)
@鉴别器列(name=“TYPE”)
公共抽象类人物{
@实体
@鉴别器值(“Plantiff”)
公共类Plantiff扩展个人{
@实体
@鉴别器价值(“被告”)
公共类被告人{
@实体
@鉴别器价值(“律师”)
公营律师{
这是正确的,因为我可以查询单个类别,并且过滤器是自动的,例如Plantiff上的findAll
将获得所有时间的Plantiff
现在我正试图通过案件中的人员将他们与诉讼联系起来
@JoinTable:
@实体
@表(name=“诉讼”)
公开诉讼{
@身份证
长id;
字符串标题;
@独身癖
@JoinTable(name=“PERSONS”,
joinColumns=@JoinColumn(name=“ID\u”,referencedColumnName=“ID”),
inverseJoinColumns=@JoinColumn(name=“ID\u PERSON”,referencedColumnName=“ID”))
普兰提夫普兰提夫;
@许多
@JoinTable(name=“PERSONS”,
joinColumns=@JoinColumn(name=“ID\u”,referencedColumnName=“ID”),
inverseJoinColumns=@JoinColumn(name=“ID\u PERSON”,referencedColumnName=“ID”))
确定被告;
...
}
这就是问题的症结所在:未应用@DiscriminatorValue
,它似乎被@JoinTable
完全绕过了
事实上,集合
不仅包含被告,还包含案件中的每个人(关系表中的每个记录。例如,如果我有一个植物人、一名法官、两名被告和两名律师,上述集合
将包含6人而不是2人)
如何使@DiscriminatorValue
通过@JoinTable
绑定工作?
编辑:我使用的是Hibernate 3.6.6.Final,而且(尽管我总是尽量避免)我对供应商特定的解决方案持开放态度,比如
@ForceDiscriminator
(不推荐)、@DiscriminatorOptions(force=true)
等等。我在询问之前显然已经尝试过(但无法让它工作).在标准JPA中,没有办法共享联接表,并且在联接表中有一个额外的列作为一种类型的区分符,以区分它用于哪个关系
您可以使用一个单独的连接表,或者深入了解您的JPA提供商支持的供应商扩展;我知道DataNucleus JPA确实允许您需要的东西(请参阅,对于JDO,但它也适用于JPA)并期望其他提供商可能有一些方法来做到这一点,但你会使你的应用程序在JPA提供商方面不可移植
或者重新设计关系,如果这是您的项目的一个选项,简而言之,
@DiscriminatorColumn
似乎并不意味着为您区分层次结构。换句话说,如果所有内容都放在一个列表中,那么discriminator列在一个简单的级别上工作。当我开始尝试要求它分离时将实体划分成单独的列表,然后我说有问题,就像你一样
我基本上尝试了您描述的内容,但没有额外的JoinColumn
注释,我无法插入,因为创建的join表中有两个独立的id
,一个用于一个类,一个用于另一个类,任何插入都不能同时满足这两个要求。使用额外的注释来控制jo在配置中,仍然存在问题。我可以插入内容,但无法检索
基本上,您可以将@MappedSuperclass视为设计考虑事项的解决方案。Person
将是MappedSuperclass
实体,它将是抽象的,律师、法官、原告、被告等将是具体的子类
@MappedSuperclass
public abstract class Content
{
@Id @GeneratedValue private Integer id;
public Integer getId() {
return id;
}
}
作为康奈特的班级
@Entity
public class EnglishContent extends Content {
@Override
public String toString() {
return "EnglishContent:"+getId();
}
}
及
还有一些东西来支撑他们:
@Entity
public class Question {
@Id @GeneratedValue private Integer id;
@OneToMany(cascade=CascadeType.ALL)
List<EnglishContent> englishContents;
@OneToMany(cascade=CascadeType.ALL)
List<SpanishContent> spanishContents;
... getters, setters,
}
所以,不是相同的类,但它提供了单独的列表,具有多态性,而且看起来更简洁。当然,有更多的数据库表,但这不应该是主要考虑因素
希望这能有所帮助。在hibernate 5.4.2中它仍然被忽略,我们的解决方法是使用hibernate中的@Where
注释,仍然不是最佳的您试图为两个不同的事物重用联接表;这将导致混乱,因为它无法从联接表中知道它用于哪个关系,因此会误解事物。使用单独的连接表。一些JPA实现可能支持共享连接表(DataNucleus不支持IIRC,在一段时间内没有使用该功能),但这不是JPA的一部分spec@NeilStockton谢谢。事实上,案例中的人员也有一个列角色,指定该人员在该案例中所做的事情。这有什么帮助吗?这是一个旧项目(和数据库)我们现在正在迁移到JPA,如果可能的话,最好不要完全更改数据库我也不能让它正常工作,我得到“加载的对象属于错误的类”从Hibernate因为它的混乱。作为一个旁观者,认为在一个集体诉讼中,可以有不止一个原告,或者Joodor,或者其他原因。当然,诉讼只是一个假的例子,我的软件甚至不在这附近,但是谢谢。我也在使用Hibernate(在这个问题上忘了提到它)。我也得到了你同样的错误:/我会再处理一下。谢谢你,尼古拉斯,那是另一种方式。我们的问题是我们
@Entity
public class Question {
@Id @GeneratedValue private Integer id;
@OneToMany(cascade=CascadeType.ALL)
List<EnglishContent> englishContents;
@OneToMany(cascade=CascadeType.ALL)
List<SpanishContent> spanishContents;
... getters, setters,
}
Question q = new Question();
SpanishContent sc = new SpanishContent();
List<SpanishContent> spanishContents = new ArrayList<SpanishContent>();
spanishContents.add(sc);
q.setSpanishContents(spanishContents);
EnglishContent ec = new EnglishContent();
List<EnglishContent> englishContents = new ArrayList<EnglishContent>();
englishContents.add(ec);
q.setEnglishContents(englishContents);
em.persist(q);
Question q = em.find(Question.class, 1);
System.out.println(q);