简体   繁体   English

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

[英]JPA LOJ (left outer join) : Cannot join to attribute of basic type

I have two entities I want to do an LOJ on using JPA and a criteria query. 我有两个实体,我想就使用JPA和条件查询做一个LOJ。 Sounds easy enough but I am running into a problem. 听起来很简单,但我遇到了问题。 My entities: 我的实体:

@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;
}

and

@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;
}

My criteria query/join: 我的条件查询/加入:

        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);
        }

Later I add a filter criteria for reg file, as in: 稍后,我为reg文件添加过滤条件,如下所示:

predicates.add(cb.like(cb.trim(cb.lower((previewSearch.get("aFileNo")))), "%" + legacySearchCriteria.getAFileNo() + "%"));

then add the preds to the query: 然后将preds添加到查询中:

criteriaQuery.select(previewSearch).where(predicates.toArray(new Predicate[]{}));

then: 然后:

Query query = em.createQuery(criteriaQuery);
List<Table1> results = getResults(query);

The code around the getting of results and all is proven. 关于获得结果以及所有结果的代码已得到证明。 That isn't the issue. 那不是问题。 It has something to do with the way I have my entities annotated or similar. 这与我对实体进行注释或类似的方式有关。 When I run the query when I have the "AFile" in the query (triggering the creation of a Join object in my code), I get a stacktrace whose base error is: 当我在查询中有“ 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)

I have hit this site et al. 我已经点击了这个网站等。 and nothing there looks like it has a fix for me, though I tried several things. 尽管我尝试了几件事,但似乎没有什么可以解决我的问题。 Anyone have ideas? 有人有想法吗?

---- UPDATE ---- ----更新----

In essence I was looking to do a: 本质上,我一直在寻找做一个:

select fields from Table1 t1 left join Table2 t2 on t1.f1=t2.f1 where t2.f2 = 'somevalue'

Lessons learned: f1 must be the Id column of the JPA entities being joined or else you don't get it. 经验教训:f1必须是要加入的JPA实体的ID列,否则您将无法获得它。 The final answer looks like this: 最终答案如下所示:

Entities: 实体:

 @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;
 }

and

@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;
}

Code: 码:

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);

Then run the query. 然后运行查询。 That actuallly works. 这实际上有效。 Finally. 最后。

A join forms an aggregate of two entity types, yielding entity tuples. 联接形成两个实体类型的集合,产生实体元组。 You are expected to designate an attribute identifying the relationship characterizing the join, not the join column. 您应该指定一个属性,该属性标识表征连接的关系,而不是连接列。 Something like this: 像这样:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM