我有两个要使用JPA和条件查询的LOJ。听起来很简单,但我遇到了问题。我的实体:
@Data
@ToString
@Entity
@Table(name = "TABLE1")
public class Table1 {
@Id
@SuppressWarnings("all")
@Column(name = "ROWID")
private String rowId;
@Column(name = "SOME_ID")
private String someId;
....
@ManyToMany
@JoinColumn(name = "SOME_ID", referencedColumnName = "SOME_ID")
private List<Table2> table2s;
}
和
@Data
@ToString
@Entity
@Table(name = "TABLE2")
public class Table2 implements Serializable {
@Id
@SuppressWarnings("all")
@Column(name = "ROWID")
private String rowId;
@Column(name = "SOME_ID")
private String someIdAsId;
....
@ManyToMany(fetch = FetchType.LAZY, mappedBy = "table2s")
private List<Table1> table1s;
}
我的条件查询/加入:
EntityManager em = getEntityManager();
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Object> criteriaQuery = cb.createQuery();
criteriaQuery.distinct(true);
Root<Table1> previewSearch = criteriaQuery.from(Table1.class);
if(searchFields.contains(A_FILE)) {
Join<Table1, Table2> join = previewSearch.join("someId", JoinType.LEFT);
}
稍后,我为reg文件添加一个过滤条件,如下所示:
predicates.add(cb.like(cb.trim(cb.lower((previewSearch.get("aFileNo")))), "%" + legacySearchCriteria.getAFileNo() + "%"));
然后将preds添加到查询中:
criteriaQuery.select(previewSearch).where(predicates.toArray(new Predicate[]{}));
然后:
Query query = em.createQuery(criteriaQuery);
List<Table1> results = getResults(query);
关于获得结果和所有结果的代码已得到证明。那不是问题。这与我对实体进行注释或类似的方式有关。当我在查询中有“ AFile”时运行查询(触发在我的代码中创建Join对象)时,我得到一个堆栈跟踪,其基本错误是:
Caused by: org.hibernate.jpa.criteria.BasicPathUsageException: Cannot join to attribute of basic type
at org.hibernate.jpa.criteria.path.AbstractFromImpl.constructJoin(AbstractFromImpl.java:254)
at org.hibernate.jpa.criteria.path.AbstractFromImpl.join(AbstractFromImpl.java:247)
at org.hibernate.jpa.criteria.path.AbstractFromImpl.join(AbstractFromImpl.java:422)
at com.xxx.ent.dataobjects.common.dao.SearchDao.executeQuery(PreviewConditionalSearchDao.java:77)
at com.xxx.ent.dataobjects.common.dao.SearchDao.getPreview(PreviewConditionalSearchDao.java:46)
at sun.reflect.GeneratedMethodAccessor20.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
我已经访问了该网站等。尽管我尝试了几件事,但似乎没有什么可以解决我的问题。有人有主意吗?
----更新----
从本质上讲,我正在考虑做一个:
select fields from Table1 t1 left join Table2 t2 on t1.f1=t2.f1 where t2.f2 = 'somevalue'
经验教训:f1必须是要加入的JPA实体的ID列,否则您将无法获得它。最终答案如下:
实体:
@Data
@ToString
@Entity
@Table(name = "TABLE_1")
public class Table1 {
@Id
@Column(name = "ID")
private String id;
....
@ManyToOne(fetch=FetchType.LAZY)
@JoinColumn(name = "ID", referencedColumnName = "ID", insertable=false, updatable=false)
private Table2 table2;
}
和
@Data
@ToString
@Entity
@Table(name = "TABLE_2")
public class Table2 {
@Id
@Column(name = "ID")
private String id;
@Column(name = "FIELD_2")
private String f2;
@OneToMany(fetch = FetchType.LAZY, mappedBy = "table2")
private List<Table1> table1s;
}
代码:
EntityManager entityManager = getEntityManager();
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<Object> criteriaQuery = cb.createQuery();
criteriaQuery.distinct(true);
Root<Table1> table1Root = criteriaQuery.from(Table1.class);
Path field2Path = null;
if(searchFields.contains(FIELD2)) {
Join<Table1, Table2> field2Join = table1Root.join("table2", JoinType.LEFT);
field2Path = field2Join.get("f2");
}
List<Predicate> predicates = new ArrayList<>();
// add preds ...
case SOME_PRED:
predicates.add(cb.like(cb.trim(cb.lower((table1Root.get("somePred")))), "%" + criteria.getSomePred() + "%"));
break;
case FIELD2:
predicates.add(cb.like(cb.trim(cb.lower((field2Path))), "%" + criteria.getField2() + "%"));
break;
....
criteriaQuery.select(table1Root).where(predicates.toArray(new Predicate[]{}));
Query query = entityManager.createQuery(criteriaQuery);
然后运行查询。这实际上有效。最后。
答案 0 :(得分:1)
联接形成两个实体类型的集合,产生实体元组。您应该指定一个属性,该属性标识表征连接的关系,而不是连接列。像这样:
Join<Table1, Table2> join = previewSearch.join("table2s", JoinType.LEFT);