【问题标题】:error creating alias while using hibernate inheritance table per concrete class在为每个具体类使用休眠继承表时创建别名时出错
【发布时间】:2016-01-05 15:05:45
【问题描述】:

我有一个模型,我在其中为每个具体类实现了表。所以我有一个抽象类,它具有跨多个表的公共属性。我有以下实体。

    @Entity
    @Inheritance(strategy=InheritanceType.TABLE_PER_CLASS)
    public abstract class BaseForm{

    @Id
    @GeneratedValue(strategy = GenerationType.TABLE)
    protected Long id;

    public Long getId() {
        return id;
    }
    public void setId(Long id) {
        this.id=id;
    }

    @Column(name = "submission_date")
    protected Date submissionDate;

    public Date getSubmissionDate() {
        return submissionDate;
    }
    public void setSubmissionDate(Date submissionDate) {
        this.submissionDate=submissionDate;
    }

   }

@Entity
@Table(name = "form_a")
public class FormA extends BaseForm{

    @OneToMany(cascade = CascadeType.ALL, mappedBy = "formA", fetch = FetchType.LAZY)
    @Cascade(value = org.hibernate.annotations.CascadeType.DELETE_ORPHAN)
    @Fetch(FetchMode.SUBSELECT)
    @OrderBy("id")
    protected List<UserForm> userForms = new ArrayList<UserForm>();

}

@Entity
@Table(name = "form_b")
public class FormB extends BaseForm{

    @OneToMany(cascade = CascadeType.ALL, mappedBy = "formB", fetch = FetchType.LAZY)
    @Cascade(value = org.hibernate.annotations.CascadeType.DELETE_ORPHAN)
    @Fetch(FetchMode.SUBSELECT)
    @OrderBy("id")
    protected List<UserForm> userForms = new ArrayList<UserForm>();

}

@Entity
@Table(name = "user_form")
public class UserForm {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    protected Long id;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    @ManyToOne(optional = true)
    protected FormA formA;

    @ManyToOne(optional = true)
    protected FormB formB;

    @ManyToOne(optional = true)
    protected User user;    

}

但每当我尝试在多态查询上使用 createAlias 时,都会选择所有加入 userForms 的表单以返回每个表单的用户信息。它引发了一个例外。 2016-01-04 12:21:54,158 错误 [org.hibernate.util.JDBCExceptionReporter] 不是唯一的表/别名:'userforms1_'

    DetachedCriteria baseCR = DetachedCriteria.forClass(BaseForm.class);
    baseCR.createAlias("userForms", "userForms");
            );
    baseCR.add(Restrictions.disjunction()
        .add(Restrictions.isNotNull("userForms.formA"))
        .add(Restrictions.isNotNull("userForms.formB"))
    ); 
    baseCR.setResultTransformer(CriteriaSpecification.DISTINCT_ROOT_ENTITY);
    baseCR.setProjection(Projections.rowCount());
    List results= ht.findByCriteria(baseCR);    

这是生成的休眠查询

SELECT COUNT(*) AS y0_
FROM
  (SELECT id,
    submissionDate,  
    1 AS clazz_
  FROM form_a
  UNION
  SELECT id,
    submissionDate,  
    2 AS clazz_
  FROM form_b
  ) this_
INNER JOIN user_form userforms1_
ON this_.id=userforms1_.formA_id
INNER JOIN user_form userforms1_
ON this_.id=userforms1_.formB_id
WHERE (userforms1_.formA IS NOT NULL
OR userforms1_.formB IS NOT NULL)

知道会是什么问题。以及如何解决?

【问题讨论】:

    标签: java hibernate polymorphism


    【解决方案1】:

    您正在使用超类别名访问子类字段,这在概念上是错误的(尽管在某些情况下有效,但显然并非总是如此)。

    您应该考虑将 userForms 移动到基类或将您的查询转换为类似的内容(JPQL,只需将其转换为等效的 Criteria):

    select bf from BaseForm bf 
      where bf.id in (select fa.id from FormA fa join fa.userForms)
         or bf.id in (select fb.id from FormB fb join fb.userForms)
    

    【讨论】:

    • 感谢您抽出宝贵时间回答我的问题。但实际上 hql 并没有解决问题,因为 FormA 和 FormB 每个人都有自己的 id 序列。所以我们可能在 FormA 中有 ID10,在 FormB 中有另一个 ID 10
    • 在这种情况下,恐怕您遇到的问题比这要大得多。 entityManager.find(BaseForm.class, 10)(或 Hibernate Session 的等效操作)的预期结果是什么?
    • 我明白你的观点 @GeneratedValue(strategy = GenerationType.TABLE) 会处理所有实体中 id 的唯一性。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-31
    • 1970-01-01
    • 1970-01-01
    • 2016-10-04
    • 1970-01-01
    相关资源
    最近更新 更多