JPA LOJ(左外部联接):无法联接到基本类型的属性

时间:2019-04-30 23:15:57

标签: java hibernate jpa

我有两个要使用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);

然后运行查询。这实际上有效。最后。

1 个答案:

答案 0 :(得分:1)

联接形成两个实体类型的集合,产生实体元组。您应该指定一个属性,该属性标识表征连接的关系,而不是连接列。像这样:

        Join<Table1, Table2> join = previewSearch.join("table2s", JoinType.LEFT);