在使用hibernate和jpa的spring mvc应用程序中,我在WordKey
实体和Concept
实体之间存在多对多关系。 WordKey
具有concepts
集合,而Concept
具有wordkeys
集合。我不想使用fetchType=EAGER
,因为性能是一个问题。相反,一旦用户选择了WordKey
,我想用将Collection<Concept>
selectedKeyWord
作为参数并返回关联的wk
集合的查询结果填充concepts
。与基础数据库中的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_junction
实体代码中指定的WordKey
连接表: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;
}
}
最佳答案
我认为您需要在@ManyToMany(cascade={CascadeType.ALL})
类中的Concept
中使用maptedBy。添加将注释更改为@ManyToMany(cascade={CascadeType.ALL}, mappedBy="concepts")
,然后重试。
您需要使用它来告诉Hibernate将您的wordKey
的多对多集合映射到Concept
类上的WordKey
的集合,这又会将您的wordkey_junction
表公开给该集合。
如果这不起作用,或者您不希望建立双向关系,请告诉我。