【问题标题】:hibernate not locating junction table in query of many to many relationshiphibernate在多对多关系的查询中没有定位联结表
【发布时间】:2014-05-15 23:20:57
【问题描述】:

在使用 hibernate 和 jpa 的 spring mvc 应用程序中,WordKey 实体和 Concept 实体之间存在多对多关系。 WordKey 有一个 concepts 集合,Concept 有一个 wordkeys 集合。我不想使用fetchType=EAGER,因为性能是个问题。相反,一旦用户选择了WordKey,我想使用以selectedKeyWordwk 作为参数并返回关联的concepts 的集合的查询结果填充Collection<Concept>在底层数据库中使用WordKey。如何在 JPQL 中编写此查询?

这是我到目前为止的查询。它不起作用(请参阅下面的错误):

@SuppressWarnings("unchecked")
public Collection<Concept> findConceptsForKeyWord(ConcWordKey wk) {
    Query query = this.em.createQuery(
        "SELECT DISTINCT concept FROM Concept concept join concept.wordkeys k WHERE k.name =:wk"
    );
    query.setParameter("wk", wk.getName());
    Collection<Concept> result = (Collection<Concept>) query.getResultList();
    return result;
}

这是上面代码生成的休眠查询。请注意,它正在寻找一个虚构的concept_wordkey 表,而不是使用在下面的WordKey 实体代码中指定的wordkey_junction 连接表:

select distinct conc0_.effectiveTime as effectiv1_52_,
 conc0_.id as id2_52_,
 from concept conc0_
 inner join concept_wordkey wordkeys1_
 on conc0_.effectiveTime=wordkeys1_.concept_effectiveTime
 and conc0_.id=wordkeys1_.concept_id
 inner join wordkey conc2_
 on wordkeys1_.wordkeys_keyword=conc2_.keyword
 where conc2_.keyword=?

堆栈跟踪中生成的具体错误是:

com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException:  
Table 'mydb.concept_wordkey' doesn't exist

这里是Concept 实体:

@Entity
@Table(name = "concept")
public class Concept implements Serializable{

    @EmbeddedId
    public EmbedPK conceptPk;

    @ManyToMany(cascade={CascadeType.ALL})
    private Set<WordKey> wordkeys;

    public EmbedPK getConceptPk(){return conceptPk;}

    protected Set<WordKey> getWordkeysInternal() {
        if (this.wordkeys == null) {this.wordkeys = new HashSet<WordKey>();}
        return this.wordkeys;
    }

    public List<WordKey> getWordkeys() {
        List<WordKey> sortedWordkeys = new ArrayList<WordKey>(getWordkeysInternal());
        PropertyComparator.sort(sortedWordkeys, new MutableSortDefinition("wordkey", true, true));
        return Collections.unmodifiableList(sortedWordkeys);
    }

    public WordKey getWordkey(String s) {return getWordkey(s, false);}

    public WordKey getWordkey(String ps, boolean ignoreNew) {
        ps = ps.toLowerCase();
        for (WordKey s1 : getWordkeysInternal()) {
            if (!ignoreNew || !s1.isNew()) {
                String keyword = s1.getName();
                keyword = keyword.toLowerCase();
                if (keyword.equals(ps)) {return s1;}
            }
        }
        return null;
    }
}

这里是WordKey 实体:

@Entity
@Table(name = "wordkey")
public class WordKey {

    @Id
    @Column(name="keyword")
    private String name;

    @ManyToMany(cascade = {CascadeType.ALL})
    @JoinTable(name="wordkey_junction",
        joinColumns={@JoinColumn(name="keyword")},
        inverseJoinColumns={@JoinColumn(name="conceptid"),@JoinColumn(name="effectiveTime")})
    private Set<Concept> concepts = new HashSet<Concept>();

    public String getName(){return name;}
    public void setName(String nm){name=nm;}

    protected Set<Concept> getConceptsInternal() {
        if (this.concepts == null) {this.concepts = new HashSet<Concept>();}
        return this.concepts;
    }

    public List<Concept> getConcepts() {
        List<Concept> sortedConcepts = new ArrayList<Concept>(getConceptsInternal());
        PropertyComparator.sort(sortedConcepts, new MutableSortDefinition("conceptid", true, true));
        return Collections.unmodifiableList(sortedConcepts);
    }

    public Concept getConcept(BigInteger s) {return getConcept(s, false);}

    public Concept getConcept(BigInteger ps, boolean ignoreNew) {
        for (Concept s1 : getConceptsInternal()) {
            if (!ignoreNew || !s1.isNew()) {
                BigInteger compName = s1.getConceptPk().getId();
                if (compName == ps) {return s1;}
            }
        }
        return null;
    }
}

【问题讨论】:

    标签: java sql spring hibernate jpa


    【解决方案1】:

    我认为您需要在 @ManyToMany(cascade={CascadeType.ALL}) 中的 Concept 类中使用 mappedBy。将您的注释更改为@ManyToMany(cascade={CascadeType.ALL}, mappedBy="concepts"),然后重试。

    你需要这个来告诉 Hibernate 将你的 wordKey 的多对多集合映射到 WordKey 类上的 Concept 的集合,这反过来会暴露你的 wordkey_junction 表收藏。

    如果这不起作用或者您不想要双向关系,请告诉我。

    【讨论】:

      【解决方案2】:

      您需要指定中间(外部参照)表。

      @ManyToMany(cascade = {CascadeType.ALL})
          @JoinTable(name = "midTableName",
                  joinColumns = {@JoinColumn(name = "foreignKey")},
                  inverseJoinColumns = {@JoinColumn(name = "OtherEntityForeignKey")})
      

      注意 - 这是具有规范化的多对多映射的一般方式。如果您可以使用表格结构更新问题,您可以获得一个很好的答案..

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-07-20
        • 1970-01-01
        • 1970-01-01
        • 2018-11-09
        • 2010-09-20
        相关资源
        最近更新 更多